Source to ./dev_c7200_eth.c


Enter a symbol's name here to quickly find it.

/*  
 * Cisco router simulation platform.
 * Copyright (c) 2005,2006 Christophe Fillot ([email protected])
 *
 * Ethernet Port Adapters.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>
#include <assert.h>

#include "utils.h"
#include "net.h"
#include "net_io.h"
#include "ptask.h"
#include "dev_am79c971.h"
#include "dev_dec21140.h"
#include "dev_i8254x.h"
#include "dev_mv64460.h"
#include "dev_c7200.h"

/* ====================================================================== */
/* C7200-IO-FE EEPROM                                                     */
/* ====================================================================== */

/* C7200-IO-FE: C7200 IOCard with one FastEthernet port EEPROM */
static const m_uint16_t eeprom_c7200_io_fe_data[] = {
   0x0183, 0x010E, 0xffff, 0xffff, 0x490B, 0x8C02, 0x0000, 0x0000,
   0x5000, 0x0000, 0x9812, 0x2800, 0x00FF, 0xFFFF, 0xFFFF, 0xFFFF,
};

static const struct cisco_eeprom eeprom_c7200_io_fe = {
   "C7200-IO-FE", (m_uint16_t *)eeprom_c7200_io_fe_data,
   sizeof(eeprom_c7200_io_fe_data)/2,
};

/*
 * dev_c7200_iocard_init()
 *
 * Add an IOcard into slot 0.
 */
static int dev_c7200_iocard_init(vm_instance_t *vm,struct cisco_card *card)
{
   struct dec21140_data *data;
   u_int slot = card->slot_id;

   if (slot != 0) {
      vm_error(vm,"cannot put IOCARD in PA bay %u!\n",slot);
      return(-1);
   }

   /* Set the PCI bus */
   card->pci_bus = vm->slots_pci_bus[slot];

   /* Set the EEPROM */
   cisco_card_set_eeprom(vm,card,&eeprom_c7200_io_fe);
   c7200_set_slot_eeprom(VM_C7200(vm),slot,&card->eeprom);

   /* Create the DEC21140 chip */
   data = dev_dec21140_init(vm,card->dev_name,
                            card->pci_bus,
                            VM_C7200(vm)->npe_driver->dec21140_pci_dev,
                            c7200_net_irq_for_slot_port(slot,0));
   if (!data) return(-1);

   /* Store device info into the router structure */
   card->drv_info = data;
   return(0);
}

/* Remove an IOcard from slot 0 */
static int dev_c7200_iocard_shutdown(vm_instance_t *vm,struct cisco_card *card)
{
   /* Remove the PA EEPROM */
   cisco_card_unset_eeprom(card);
   c7200_set_slot_eeprom(VM_C7200(vm),card->slot_id,NULL);

   /* Shutdown the DEC21140 */
   dev_dec21140_remove(card->drv_info);
   return(0);
}

/* Bind a Network IO descriptor */
static int dev_c7200_iocard_set_nio(vm_instance_t *vm,struct cisco_card *card,
                                    u_int port_id,netio_desc_t *nio)
{
   struct dec21140_data *d = card->drv_info;

   if (!d || (port_id > 0))
      return(-1);

   return(dev_dec21140_set_nio(d,nio));
}

/* Unbind a Network IO descriptor */
static int dev_c7200_iocard_unset_nio(vm_instance_t *vm,
                                      struct cisco_card *card,
                                      u_int port_id)
{
   struct dec21140_data *d = card->drv_info;

   if (!d || (port_id > 0))
      return(-1);
   
   dev_dec21140_unset_nio(d);
   return(0);
}

/*
 * dev_c7200_pa_fe_tx_init()
 *
 * Add a PA-FE-TX port adapter into specified slot.
 */
static int dev_c7200_pa_fe_tx_init(vm_instance_t *vm,struct cisco_card *card)
{
   struct dec21140_data *data;
   u_int slot = card->slot_id;

   /* Set the PCI bus */
   card->pci_bus = vm->slots_pci_bus[slot];

   /* Set the EEPROM */
   cisco_card_set_eeprom(vm,card,cisco_eeprom_find_pa("PA-FE-TX"));
   c7200_set_slot_eeprom(VM_C7200(vm),slot,&card->eeprom);

   /* Create the DEC21140 chip */
   data = dev_dec21140_init(vm,card->dev_name,card->pci_bus,0,
                            c7200_net_irq_for_slot_port(slot,0));
   if (!data) return(-1);

   /* Store device info into the router structure */
   card->drv_info = data;
   return(0);
}

/* Remove a PA-FE-TX from the specified slot */
static int 
dev_c7200_pa_fe_tx_shutdown(vm_instance_t *vm,struct cisco_card *card)
{
   /* Remove the PA EEPROM */
   cisco_card_unset_eeprom(card);
   c7200_set_slot_eeprom(VM_C7200(vm),card->slot_id,NULL);

   /* Shutdown the DEC21140 */
   dev_dec21140_remove(card->drv_info);
   return(0);
}

/* Bind a Network IO descriptor */
static int 
dev_c7200_pa_fe_tx_set_nio(vm_instance_t *vm,struct cisco_card *card,
                           u_int port_id,netio_desc_t *nio)
{
   struct dec21140_data *d = card->drv_info;

   if (!d || (port_id > 0))
      return(-1);

   return(dev_dec21140_set_nio(d,nio));
}

/* Unbind a Network IO descriptor */
static int 
dev_c7200_pa_fe_tx_unset_nio(vm_instance_t *vm,struct cisco_card *card,
                             u_int port_id)
{
   struct dec21140_data *d = card->drv_info;

   if (!d || (port_id > 0))
      return(-1);
   
   dev_dec21140_unset_nio(d);
   return(0);
}

/* C7200-IO-FE driver */
struct cisco_card_driver dev_c7200_iocard_fe_driver = {
   "C7200-IO-FE", 1, 0, 
   dev_c7200_iocard_init, 
   dev_c7200_iocard_shutdown,
   NULL,
   dev_c7200_iocard_set_nio,
   dev_c7200_iocard_unset_nio,
   NULL,
};

/* PA-FE-TX driver */
struct cisco_card_driver dev_c7200_pa_fe_tx_driver = {
   "PA-FE-TX", 1, 0, 
   dev_c7200_pa_fe_tx_init, 
   dev_c7200_pa_fe_tx_shutdown,
   NULL,
   dev_c7200_pa_fe_tx_set_nio,
   dev_c7200_pa_fe_tx_unset_nio,
   NULL,
};

/* ====================================================================== */
/* PA based on Intel i8254x chips                                         */
/* ====================================================================== */

struct pa_i8254x_data {
   u_int nr_port;
   struct i8254x_data *port[2];
};

/* Remove a PA-2FE-TX from the specified slot */
static int 
dev_c7200_pa_i8254x_shutdown(vm_instance_t *vm,struct cisco_card *card)
{
   struct pa_i8254x_data *data = card->drv_info;
   int i;

   /* Remove the PA EEPROM */
   cisco_card_unset_eeprom(card);
   c7200_set_slot_eeprom(VM_C7200(vm),card->slot_id,NULL);

   /* Remove the Intel i2854x chips */
   for(i=0;i<data->nr_port;i++)
      dev_i8254x_remove(data->port[i]);

   free(data);
   return(0);
}

/* Bind a Network IO descriptor */
static int 
dev_c7200_pa_i8254x_set_nio(vm_instance_t *vm,struct cisco_card *card,
                            u_int port_id,netio_desc_t *nio)
{
   struct pa_i8254x_data *d = card->drv_info;

   if (!d || (port_id >= d->nr_port))
      return(-1);

   dev_i8254x_set_nio(d->port[port_id],nio);
   return(0);
}

/* Unbind a Network IO descriptor */
static int 
dev_c7200_pa_i8254x_unset_nio(vm_instance_t *vm,struct cisco_card *card,
                              u_int port_id)
{
   struct pa_i8254x_data *d = card->drv_info;

   if (!d || (port_id >= d->nr_port))
      return(-1);

   dev_i8254x_unset_nio(d->port[port_id]);
   return(0);
}

/* ====================================================================== */
/* PA-2FE-TX                                                              */
/* ====================================================================== */

/*
 * dev_c7200_pa_2fe_tx_init()
 *
 * Add a PA-2FE-TX port adapter into specified slot.
 */
static int dev_c7200_pa_2fe_tx_init(vm_instance_t *vm,struct cisco_card *card)
{
   struct pa_i8254x_data *data;
   u_int slot = card->slot_id;
   int i;

   /* Allocate the private data structure for the PA-2FE-TX */
   if (!(data = malloc(sizeof(*data)))) {
      vm_error(vm,"%s: out of memory\n",card->dev_name);
      return(-1);
   }

   /* 2 Ethernet ports */
   memset(data,0,sizeof(*data));
   data->nr_port = 2;

   /* Set the PCI bus */
   card->pci_bus = vm->slots_pci_bus[slot];

   /* Set the EEPROM */
   cisco_card_set_eeprom(vm,card,cisco_eeprom_find_pa("PA-2FE-TX"));
   c7200_set_slot_eeprom(VM_C7200(vm),slot,&card->eeprom);

   /* Create the Intel i8254x chips */
   for(i=0;i<data->nr_port;i++) {
      data->port[i] = dev_i8254x_init(vm,card->dev_name,0,
                                      card->pci_bus,i,
                                      c7200_net_irq_for_slot_port(slot,i));
   }

   /* Store device info into the router structure */
   card->drv_info = data;
   return(0);
}

/* PA-2FE-TX driver */
struct cisco_card_driver dev_c7200_pa_2fe_tx_driver = {
   "PA-2FE-TX", 0, 0,
   dev_c7200_pa_2fe_tx_init, 
   dev_c7200_pa_i8254x_shutdown, 
   NULL,
   dev_c7200_pa_i8254x_set_nio,
   dev_c7200_pa_i8254x_unset_nio,
   NULL,
};

/* ====================================================================== */
/* PA-GE                                                                  */
/* ====================================================================== */

/*
 * dev_c7200_pa_ge_init()
 *
 * Add a PA-GE port adapter into specified slot.
 */
static int dev_c7200_pa_ge_init(vm_instance_t *vm,struct cisco_card *card)
{
   struct pa_i8254x_data *data;
   u_int slot = card->slot_id;

   /* Allocate the private data structure for the PA-2FE-TX */
   if (!(data = malloc(sizeof(*data)))) {
      vm_error(vm,"%s: out of memory\n",card->dev_name);
      return(-1);
   }

   /* 2 Ethernet ports */
   memset(data,0,sizeof(*data));
   data->nr_port = 1;

   /* Set the PCI bus */
   card->pci_bus = vm->slots_pci_bus[slot];

   /* Set the EEPROM */
   cisco_card_set_eeprom(vm,card,cisco_eeprom_find_pa("PA-GE"));
   c7200_set_slot_eeprom(VM_C7200(vm),slot,&card->eeprom);

   /* Create the Intel i8254x chip */
   data->port[0] = dev_i8254x_init(vm,card->dev_name,0,
                                   card->pci_bus,0,
                                   c7200_net_irq_for_slot_port(slot,0));

   /* Store device info into the router structure */
   card->drv_info = data;
   return(0);
}

/* PA-GE driver */
struct cisco_card_driver dev_c7200_pa_ge_driver = {
   "PA-GE", 0, 0,
   dev_c7200_pa_ge_init, 
   dev_c7200_pa_i8254x_shutdown, 
   NULL,
   dev_c7200_pa_i8254x_set_nio,
   dev_c7200_pa_i8254x_unset_nio,
   NULL,
};

/* ====================================================================== */
/* C7200-IO-2FE                                                           */
/* ====================================================================== */

/* C7200-IO-2FE/E: C7200 IOCard with two FastEthernet ports EEPROM */
static const m_uint16_t eeprom_c7200_io_2fe_data[] = {
   0x04FF, 0x4002, 0x1541, 0x0201, 0xC046, 0x0320, 0x001B, 0xCA06,
   0x8249, 0x138B, 0x0642, 0x4230, 0xC18B, 0x3030, 0x3030, 0x3030,
   0x3030, 0x0000, 0x0004, 0x0002, 0x0385, 0x1C0D, 0x7F03, 0xCB8F,
   0x4337, 0x3230, 0x302D, 0x492F, 0x4F2D, 0x3246, 0x452F, 0x4580,
   0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
   0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
   0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
   0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
};

static const struct cisco_eeprom eeprom_c7200_io_2fe = {
   "C7200-IO-2FE", (m_uint16_t *)eeprom_c7200_io_2fe_data,
   sizeof(eeprom_c7200_io_2fe_data)/2,
};

/*
 * dev_c7200_pa_2fe_tx_init()
 *
 * Add a C7200-IO-2FE/E port adapter into specified slot.
 */
static int dev_c7200_iocard_2fe_init(vm_instance_t *vm,struct cisco_card *card)
{
   struct pa_i8254x_data *data;
   u_int slot = card->slot_id;

   /* Allocate the private data structure for the iocard */
   if (!(data = malloc(sizeof(*data)))) {
      vm_error(vm,"%s: out of memory\n",card->dev_name);
      return(-1);
   }

   /* 2 Ethernet ports */
   memset(data,0,sizeof(*data));
   data->nr_port = 2;

   /* Set the PCI bus */
   card->pci_bus = vm->slots_pci_bus[slot];

   /* Set the EEPROM */
   cisco_card_set_eeprom(vm,card,&eeprom_c7200_io_2fe);
   c7200_set_slot_eeprom(VM_C7200(vm),slot,&card->eeprom);

   /* Port Fa0/0 is on PCI Device 1 */
   data->port[0] = dev_i8254x_init(vm,card->dev_name,0,
                                   card->pci_bus,1,
                                   c7200_net_irq_for_slot_port(slot,1));

   /* Port Fa0/1 is on PCI Device 0 */
   data->port[1] = dev_i8254x_init(vm,card->dev_name,0,
                                   card->pci_bus,0,
                                   c7200_net_irq_for_slot_port(slot,0));

   if (!data->port[0] || !data->port[1]) {
      dev_i8254x_remove(data->port[0]);
      dev_i8254x_remove(data->port[1]);
      free(data);
      return(-1);
   }

   /* Store device info into the router structure */
   card->drv_info = data;
   return(0);
}

/* C7200-IO-2FE driver */
struct cisco_card_driver dev_c7200_iocard_2fe_driver = {
   "C7200-IO-2FE", 0, 0,
   dev_c7200_iocard_2fe_init, 
   dev_c7200_pa_i8254x_shutdown, 
   NULL,
   dev_c7200_pa_i8254x_set_nio,
   dev_c7200_pa_i8254x_unset_nio,
   NULL,
};

/* ====================================================================== */
/* C7200-IO-GE-E                                                          */
/* ====================================================================== */

/* 
 * C7200-IO-GE+E: C7200 IOCard with 1 GigatEthernet ports 
 * and 1 Ethernet port EEPROM.
 */
static const m_uint16_t eeprom_c7200_io_ge_e_data[] = {
   0x04FF, 0x4002, 0x1641, 0x0201, 0xC046, 0x0320, 0x001B, 0xCA06,
   0x8249, 0x138B, 0x0642, 0x4230, 0xC18B, 0x3030, 0x3030, 0x3030,
   0x3030, 0x0000, 0x0004, 0x0002, 0x0385, 0x1C0D, 0x7F03, 0xCB8F,
   0x4337, 0x3230, 0x302D, 0x492F, 0x4F2D, 0x3246, 0x452F, 0x4580,
   0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
   0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
   0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
   0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
};

static const struct cisco_eeprom eeprom_c7200_io_ge_e = {
   "C7200-IO-GE-E", (m_uint16_t *)eeprom_c7200_io_ge_e_data,
   sizeof(eeprom_c7200_io_ge_e_data)/2,
};

/*
 * dev_c7200_pa_ge_e_tx_init()
 *
 * Add a C7200-I/O-GE+E port adapter into specified slot.
 */
static int 
dev_c7200_iocard_ge_e_init(vm_instance_t *vm,struct cisco_card *card)
{
   struct pa_i8254x_data *data;
   u_int slot = card->slot_id;

   /* Allocate the private data structure for the iocard */
   if (!(data = malloc(sizeof(*data)))) {
      vm_error(vm,"%s: out of memory\n",card->dev_name);
      return(-1);
   }

   /* 2 Ethernet ports */
   memset(data,0,sizeof(*data));
   data->nr_port = 2;

   /* Set the PCI bus */
   card->pci_bus = vm->slots_pci_bus[slot];

   /* Set the EEPROM */
   cisco_card_set_eeprom(vm,card,&eeprom_c7200_io_ge_e);
   c7200_set_slot_eeprom(VM_C7200(vm),slot,&card->eeprom);

   /* Port Gi0/0 is on PCI Device 1 */
   data->port[0] = dev_i8254x_init(vm,card->dev_name,0,
                                   card->pci_bus,1,
                                   c7200_net_irq_for_slot_port(slot,1));

   /* Port e0/0 is on PCI Device 0 */
   data->port[1] = dev_i8254x_init(vm,card->dev_name,0,
                                   card->pci_bus,0,
                                   c7200_net_irq_for_slot_port(slot,0));

   /* Store device info into the router structure */
   card->drv_info = data;
   return(0);
}

/* C7200-IO-GE-E driver */
struct cisco_card_driver dev_c7200_iocard_ge_e_driver = {
   "C7200-IO-GE-E", 0, 0,
   dev_c7200_iocard_ge_e_init, 
   dev_c7200_pa_i8254x_shutdown, 
   NULL,
   dev_c7200_pa_i8254x_set_nio,
   dev_c7200_pa_i8254x_unset_nio,
   NULL,
};

/* ====================================================================== */
/* PA-4E / PA-8E                                                          */
/* ====================================================================== */

/* PA-4E/PA-8E data */
struct pa_4e8e_data {
   u_int nr_port;
   struct am79c971_data *port[8];
};

/*
 * dev_c7200_pa_4e_init()
 *
 * Add a PA-4E port adapter into specified slot.
 */
static int dev_c7200_pa_4e_init(vm_instance_t *vm,struct cisco_card *card)
{
   struct pa_4e8e_data *data;
   u_int slot = card->slot_id;
   int i;

   /* Allocate the private data structure for the PA-4E */
   if (!(data = malloc(sizeof(*data)))) {
      vm_error(vm,"%s: out of memory\n",card->dev_name);
      return(-1);
   }

   /* 4 Ethernet ports */
   memset(data,0,sizeof(*data));
   data->nr_port = 4;

   /* Set the PCI bus */
   card->pci_bus = vm->slots_pci_bus[slot];

   /* Set the EEPROM */
   cisco_card_set_eeprom(vm,card,cisco_eeprom_find_pa("PA-4E"));
   c7200_set_slot_eeprom(VM_C7200(vm),slot,&card->eeprom);

   /* Create the AMD Am79c971 chips */
   for(i=0;i<data->nr_port;i++) {
      data->port[i] = dev_am79c971_init(vm,card->dev_name,
                                        AM79C971_TYPE_10BASE_T,
                                        card->pci_bus,i,
                                        c7200_net_irq_for_slot_port(slot,i));
   }

   /* Store device info into the router structure */
   card->drv_info = data;
   return(0);
}

/*
 * dev_c7200_pa_8e_init()
 *
 * Add a PA-8E port adapter into specified slot.
 */
static int dev_c7200_pa_8e_init(vm_instance_t *vm,struct cisco_card *card)
{
   struct pa_4e8e_data *data;
   u_int slot = card->slot_id;
   int i;

   /* Allocate the private data structure for the PA-8E */
   if (!(data = malloc(sizeof(*data)))) {
      vm_error(vm,"%s: out of memory\n",card->dev_name);
      return(-1);
   }

   /* 4 Ethernet ports */
   memset(data,0,sizeof(*data));
   data->nr_port = 8;

   /* Set the PCI bus */
   card->pci_bus = vm->slots_pci_bus[slot];

   /* Set the EEPROM */
   cisco_card_set_eeprom(vm,card,cisco_eeprom_find_pa("PA-8E"));
   c7200_set_slot_eeprom(VM_C7200(vm),slot,&card->eeprom);

   /* Create the AMD Am79c971 chips */
   for(i=0;i<data->nr_port;i++) {
      data->port[i] = dev_am79c971_init(vm,card->dev_name,
                                        AM79C971_TYPE_10BASE_T,
                                        card->pci_bus,i,
                                        c7200_net_irq_for_slot_port(slot,i));
   }

   /* Store device info into the router structure */
   card->drv_info = data;
   return(0);
}

/* Remove a PA-4E/PA-8E from the specified slot */
static int 
dev_c7200_pa_4e8e_shutdown(vm_instance_t *vm,struct cisco_card *card)
{
   struct pa_4e8e_data *data = card->drv_info;
   int i;

   /* Remove the PA EEPROM */
   cisco_card_unset_eeprom(card);
   c7200_set_slot_eeprom(VM_C7200(vm),card->slot_id,NULL);

   /* Remove the AMD Am79c971 chips */
   for(i=0;i<data->nr_port;i++)
      dev_am79c971_remove(data->port[i]);

   free(data);
   return(0);
}

/* Bind a Network IO descriptor */
static int 
dev_c7200_pa_4e8e_set_nio(vm_instance_t *vm,struct cisco_card *card,
                          u_int port_id,netio_desc_t *nio)
{
   struct pa_4e8e_data *d = card->drv_info;

   if (!d || (port_id >= d->nr_port))
      return(-1);

   dev_am79c971_set_nio(d->port[port_id],nio);
   return(0);
}

/* Unbind a Network IO descriptor */
static int 
dev_c7200_pa_4e8e_unset_nio(vm_instance_t *vm,struct cisco_card *card,
                            u_int port_id)
{
   struct pa_4e8e_data *d = card->drv_info;

   if (!d || (port_id >= d->nr_port))
      return(-1);

   dev_am79c971_unset_nio(d->port[port_id]);
   return(0);
}

/* PA-4E driver */
struct cisco_card_driver dev_c7200_pa_4e_driver = {
   "PA-4E", 1, 0,
   dev_c7200_pa_4e_init, 
   dev_c7200_pa_4e8e_shutdown, 
   NULL,
   dev_c7200_pa_4e8e_set_nio,
   dev_c7200_pa_4e8e_unset_nio,
   NULL,
};

/* PA-8E driver */
struct cisco_card_driver dev_c7200_pa_8e_driver = {
   "PA-8E", 1, 0,
   dev_c7200_pa_8e_init, 
   dev_c7200_pa_4e8e_shutdown, 
   NULL,
   dev_c7200_pa_4e8e_set_nio,
   dev_c7200_pa_4e8e_unset_nio,
   NULL,
};

/* ====================================================================== */
/* NPE-G2                                                                 */
/* ====================================================================== */

/* Initialize NPE-G2 Ethernet ports */
static int dev_c7200_npeg2_init(vm_instance_t *vm,struct cisco_card *card)
{
   /* Nothing to do */
   card->drv_info = VM_C7200(vm)->mv64460_sysctr;
   return(0);
}

/* Shutdown NPE-G2 Ethernet ports */
static int dev_c7200_npeg2_shutdown(vm_instance_t *vm,struct cisco_card *card)
{
   /* Nothing to do */
   return(0);
}

/* Set a NIO descriptor */
static int dev_c7200_npeg2_set_nio(vm_instance_t *vm,struct cisco_card *card,
                                   u_int port_id,netio_desc_t *nio)
{
   c7200_t *router = VM_C7200(vm);
   struct mv64460_data *mv_data = router->mv64460_sysctr;

   if (!mv_data)
      return(-1);

   dev_mv64460_eth_set_nio(mv_data,port_id,nio);
   return(0);
}

/* Unbind a NIO descriptor */
static int dev_c7200_npeg2_unset_nio(vm_instance_t *vm,
                                     struct cisco_card *card,
                                     u_int port_id)
{
   c7200_t *router = VM_C7200(vm);
   struct mv64460_data *mv_data = router->mv64460_sysctr;

   if (!mv_data)
      return(-1);

   dev_mv64460_eth_unset_nio(mv_data,port_id);
   return(0);
}

/* NPE-G2 driver */
struct cisco_card_driver dev_c7200_npeg2_driver = {
   "NPE-G2", 1, 0,
   dev_c7200_npeg2_init, 
   dev_c7200_npeg2_shutdown, 
   NULL,
   dev_c7200_npeg2_set_nio,
   dev_c7200_npeg2_unset_nio,
   NULL,
};