⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cf_io.c

📁 marvell cf wifi driver source code CF-8385-linux-x86-5.0.4.p0-132-src.rar
💻 C
字号:
/*
 * File cfio.c
 **/

#include  "cfio_io.h"

#define __NO_VERSION__

int *register_cf_driver(cf_notifier_fn_add, cf_notifier_fn_remove , void *);
void unregister_cf_driver(void);
int cfio_read_cfg_reg(void* priv);

#define CS_ERROR(h,f,r) { \
        error_info_t  err = {f,r}; \
        CardServices(ReportError,h,&err); \
      }

/*
  The bus_operations pointer is used on platforms for which we need
  to use special socket-specific versions of normal IO primitives
  (inb, outb, readb, writeb, etc) for card IO.
*/

static  void cf_config(dev_link_t * link);
static  void cf_release(ulong arg);
static  int cf_event(event_t event, int priority, event_callback_args_t * args);
static  dev_link_t *cf_attach(void);
static  void cf_detach(dev_link_t *);

dev_info_t cfio_dev_info = "mcf25";
dev_link_t *dev_list = NULL;

struct cf_card_rec cardp;

EXPORT_SYMBOL_NOVERS(cardp);
EXPORT_SYMBOL_NOVERS(cfio_dev_info);

typedef struct _if_pcmcia_info_t {
  dev_link_t link;
  dev_node_t node;
  int stop;
  struct bus_operations *bus;
  struct net_device *eth_dev;
} if_pcmcia_info_t;

/*
  MODULE PARAMETERS
*/

EXPORT_SYMBOL_NOVERS(register_cf_driver);
EXPORT_SYMBOL_NOVERS(unregister_cf_driver);
EXPORT_SYMBOL_NOVERS(cfio_read_cfg_reg);

#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")

MODULE_PARM(interrupt_steer, "1-4i");

#ifdef  ORIGINAL_CODE
INT_MODULE_PARM(free_ports, 0);
#endif

INT_MODULE_PARM(irq_mask, 0xdeb8);

/* Module Variables */
static int interrupt_steer[4] = { -1 };

void break1(void){}

dev_link_t *cf_attach(void)
{
  int i, status;
  if_pcmcia_info_t *ifinfo;
  dev_link_t *link;
  client_reg_t client_reg;

  printk("Entering cf_attach()\n");

  /* Allocate space for PCMCIA information */
  if (!(ifinfo = kmalloc(sizeof(if_pcmcia_info_t), GFP_KERNEL))) {
    return NULL;
  }

  memset(ifinfo, 0, sizeof(if_pcmcia_info_t));
  link = &ifinfo->link;
  link->priv = ifinfo;

  init_timer(&link->release);
  link->release.function = &cf_release;
  link->release.data = (ulong) link;

  link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
  link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
  
  /* Is the IRQ specified by the user? */
  if (interrupt_steer[0] == -1) {
    /* No, find the required IRQ */
    link->irq.IRQInfo2 = irq_mask;
  } else {
    /* Yes, create the mask based on user specified IRQ's */
    for (i = 0; i < 4; i++) {
      link->irq.IRQInfo2 |= 1 << interrupt_steer[i];
    }
  }

  /* Handler will be installed later */
  link->irq.Handler = NULL;

  link->conf.Attributes = 0;
  link->conf.Vcc = 50;
  link->conf.Vpp1 = 0;
  link->conf.Vpp2 = 0;
  link->conf.IntType = INT_MEMORY_AND_IO;
  link->conf.ConfigIndex = 1;
  link->conf.Present = PRESENT_OPTION;

  link->next = dev_list;
  dev_list = link;
  client_reg.dev_info = &cfio_dev_info;
  client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
  client_reg.EventMask = CS_EVENT_CARD_INSERTION |
      CS_EVENT_CARD_REMOVAL | CS_EVENT_CARD_RESET;
  client_reg.event_handler = &cf_event;
  client_reg.event_callback_args.client_data = link;
  client_reg.Version = 0x0326;

  printk("Before registering the client\n");

  if ((status = CardServices(RegisterClient, &link->handle,
           &client_reg)) != CS_SUCCESS) {
    printk("Registering the client failed\n");
    CS_ERROR(link->handle, RegisterClient, status);
    cf_detach(link);
    return NULL;
  }

  printk("Leaving cf_attach()\n");

  return link;
}       /* cf_attach */

void cf_detach(dev_link_t * link)
{
  dev_link_t **p;

  for (p = &dev_list; *p; p = &(*p)->next)
    if (*p == link)
      break;

  if (*p == NULL)
    return;

  del_timer_sync(&link->release);

  if (((if_pcmcia_info_t *) link->priv)->eth_dev) {
    printk("Before calling wlan_remove function\n");
    //pwlanpriv = NULL;
    cardp.remove(&cardp);
    printk("After calling wlan_remove function\n");
  }

  if (link->state & DEV_CONFIG) {
    cf_release((u32) link);
  }

  ((if_pcmcia_info_t *) link->priv)->eth_dev = NULL;

  if (link->handle) {
    CardServices(ResetCard, link->handle);
    CardServices(DeregisterClient, link->handle);
  }

  *p = link->next;
  /* This points to the parent if_pcmcia_info_t struct */
  if (link->priv)
    kfree(link->priv);

#ifdef CF_MEM_CHECK
  DisplayMemCounters();
#endif
} /* cf_detach */

void cf_config(dev_link_t * link)
{
  client_handle_t handle = link->handle;
  if_pcmcia_info_t *dev = link->priv;
  tuple_t tuple;
  cisparse_t parse;
  cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
  u8 buf[64];
  config_info_t conf;

  tuple.DesiredTuple = CISTPL_CONFIG;
  tuple.Attributes = 0;
  tuple.TupleData = buf;
  tuple.TupleDataMax = sizeof(buf);
  tuple.TupleOffset = 0;

  if (CardServices(GetFirstTuple, handle, &tuple))
    goto onerror;
  if (CardServices(GetTupleData, handle, &tuple))
    goto onerror;
  if (CardServices(ParseTuple, handle, &tuple, &parse))
    goto onerror;

  link->conf.ConfigBase = parse.config.base;
  link->conf.Present = parse.config.rmask[0];

  link->state |= DEV_CONFIG;

  if (CardServices(GetConfigurationInfo, handle, &conf))
    goto onerror;

  link->conf.Vcc = conf.Vcc;

  /*
     The Configuration table consists of a series of configuration table
     entry tuples. Each entry consists of up to seven data structures that
     describe operational characteristsics of the PC card.
   */

  tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;

  if (CardServices(GetFirstTuple, handle, &tuple))
    goto onerror;

  if (CardServices(GetTupleData, handle, &tuple) != CS_SUCCESS)
    goto onerror;

  if (CardServices(ParseTuple, handle, &tuple, &parse) != CS_SUCCESS)
    goto onerror;


  link->conf.ConfigIndex = cfg->index;

  /* Interrupt request description */

  if (cfg->irq.IRQInfo1)
    link->conf.Attributes |= CONF_ENABLE_IRQ;

  /* IO Address space description */

  link->io.NumPorts1 = link->io.NumPorts2 = 0;
  if ((cfg->io.nwin > 0)) {
    cistpl_io_t *io;

    if (cfg->io.nwin)
      io = &cfg->io;

    link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;

    if (!(io->flags & CISTPL_IO_8BIT))
      link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;

    if (!(io->flags & CISTPL_IO_16BIT))
      link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;

    link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;

    link->io.BasePort1 = io->win[0].base;
    link->io.NumPorts1 = io->win[0].len;

    if (io->nwin > 1) {
      link->io.Attributes2 = link->io.Attributes1;
      link->io.BasePort2 = io->win[1].base;
      link->io.NumPorts2 = io->win[1].len;
    }

    if (CardServices(RequestIO, link->handle, &link->io)
        != CS_SUCCESS) {
      CardServices(ReleaseIO, link->handle, &link->io);
      printk("Request IO Error !!\n");
      goto onerror;
    }
  }

  if (link->conf.Attributes & CONF_ENABLE_IRQ)
    if (CardServices(RequestIRQ, link->handle, &link->irq))
      goto onerror;

  if (CardServices(RequestConfiguration, link->handle, &link->conf))
    goto onerror;

  cardp.irq = link->irq.AssignedIRQ;
  cardp.port = link->io.BasePort1;
  printk("BasePort1=0x%x, AssignedIRQ=%d\n",
         link->io.BasePort1, link->irq.AssignedIRQ);

  if (!(cardp.add(&cardp))) {
    printk("Call to cardp.add failed\n");
    goto onerror;
  }

  printk("After calling wlan_add_card function\n");

  ((if_pcmcia_info_t *) link->priv)->eth_dev = cardp.eth_dev;

  if (!((if_pcmcia_info_t *) link->priv)->eth_dev)
    goto onerror;

  strcpy(dev->node.dev_name, cfio_dev_info);
  strcpy(dev->node.dev_name, cardp.eth_dev->name);
  dev->node.major = dev->node.minor = 0;
  link->dev = &dev->node;

  link->state &= ~DEV_CONFIG_PENDING;
  return;

onerror:
  printk("card configuration failed...calling cf_release function\n");
  cf_release((u32) link);
  link->state &= ~DEV_CONFIG_PENDING;
  cardp.flag = 1;

} /* cf_config */

void cf_release(ulong arg)
{
  dev_link_t *link = (dev_link_t *) arg;

  link->dev = NULL;

  CardServices(ReleaseConfiguration, link->handle);
  if (link->io.NumPorts1)
    CardServices(ReleaseIO, link->handle, &link->io);

  if (link->irq.AssignedIRQ)
    CardServices(ReleaseIRQ, link->handle, &link->irq);

  link->state &= ~DEV_CONFIG;

} /* cf_release */

int cf_event(event_t event, int priority, event_callback_args_t *args)
{
  dev_link_t *link = args->client_data;
  if_pcmcia_info_t *dev = link->priv;

  switch (event) {
  case CS_EVENT_CARD_INSERTION:
    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
    dev->bus = args->bus;
    cf_config(link);
    break;

  case CS_EVENT_CARD_REMOVAL:
    link->state &= ~DEV_PRESENT;
    printk("card removal event detected\n");
    if (link->state & DEV_CONFIG) {
      ((if_pcmcia_info_t *) link->priv)->stop = 1;
      printk("Before calling release function\n");
      mod_timer(&link->release, jiffies + HZ / 20);
      printk("After calling release function\n");
    }
    break;
  case CS_EVENT_CARD_RESET:
    if (link->state & DEV_CONFIG) {
      CardServices(RequestConfiguration,
             link->handle, &link->conf);
    }
    dev->stop = 0;
    break;
  }

  return 0;
}       /* cf_event */


int *register_cf_driver(cf_notifier_fn_add add, cf_notifier_fn_remove remove,
								void *arg)
{
  servinfo_t serv;

  cardp.add = add;
  cardp.remove = remove;
  cardp.host_int_mask = 0;

  CardServices(GetCardServicesInfo, &serv);

  if (serv.Revision != CS_RELEASE_CODE) {
    return NULL;
  }

  printk("Before calling register_pccard_driver\n");
  register_pccard_driver(&cfio_dev_info, &cf_attach, &cf_detach);
  printk("After calling register_pccard_driver\n");

  return (int *) &cardp;
}

void unregister_cf_driver()
{

  unregister_pccard_driver(&cfio_dev_info);

  cf_detach(dev_list);

  while (dev_list != NULL) {
    del_timer(&dev_list->release);
    if (dev_list->state & DEV_CONFIG)
      cf_release((u32) dev_list);
  }
}


int cfio_init_module(void)
{
  return 0;
}

void cfio_cleanup_module(void)
{

}

int cfio_read_cfg_reg(void* priv)
{
  conf_reg_t reg;

  reg.Function  = 0;
  reg.Action    = CS_READ;
  reg.Offset    = 0;
  reg.Value     = 0;

  // access the bus to wake up the device
  // O2 Micro CardBus bridge has problems of with this.  So we read
  // a configuration register instead.
  // cf_IsCmdReady(priv);

  // There is no way of getting the current handle easily!  We simply
  // get the first one from the list.  This could be a problem when you
  // have more than one instance!

  CardServices(AccessConfigurationRegister, dev_list->handle, &reg);
  return 0;
}

module_init(cfio_init_module);
module_exit(cfio_cleanup_module);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -