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

📄 nmclan_cs.c

📁 pcmcia source code
💻 C
📖 第 1 页 / 共 4 页
字号:
static void nmclan_detach(dev_link_t *);/* ----------------------------------------------------------------------------flush_stale_links	Clean up stale device structures---------------------------------------------------------------------------- */static void flush_stale_links(void){    dev_link_t *link, *next;    for (link = dev_list; link; link = next) {	next = link->next;	if (link->state & DEV_STALE_LINK)	    nmclan_detach(link);    }}/* ----------------------------------------------------------------------------cs_error	Report a Card Services related error.---------------------------------------------------------------------------- */static void cs_error(client_handle_t handle, int func, int ret){    error_info_t err = { func, ret };    CardServices(ReportError, handle, &err);}/* ----------------------------------------------------------------------------nmclan_attach	Creates an "instance" of the driver, allocating local data	structures for one device.  The device is registered with Card	Services.---------------------------------------------------------------------------- */static dev_link_t *nmclan_attach(void){    mace_private *lp;    dev_link_t *link;    struct net_device *dev;    client_reg_t client_reg;    int i, ret;    DEBUG(0, "nmclan_attach()\n");    DEBUG(1, "%s\n", rcsid);    flush_stale_links();    /* Create new ethernet device */    lp = kmalloc(sizeof(*lp), GFP_KERNEL);    if (!lp) return NULL;    memset(lp, 0, sizeof(*lp));    link = &lp->link; dev = &lp->dev;    link->priv = dev->priv = link->irq.Instance = lp;    link->release.function = &nmclan_release;    link->release.data = (u_long)link;    link->io.NumPorts1 = 32;    link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;    link->io.IOAddrLines = 5;    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;    link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;    if (irq_list[0] == -1)	link->irq.IRQInfo2 = irq_mask;    else	for (i = 0; i < 4; i++)	    link->irq.IRQInfo2 |= 1 << irq_list[i];    link->irq.Handler = &mace_interrupt;    link->conf.Attributes = CONF_ENABLE_IRQ;    link->conf.Vcc = 50;    link->conf.IntType = INT_MEMORY_AND_IO;    link->conf.ConfigIndex = 1;    link->conf.Present = PRESENT_OPTION;    lp->tx_free_frames=AM2150_MAX_TX_FRAMES;    dev->hard_start_xmit = &mace_start_xmit;    dev->set_config = &mace_config;    dev->get_stats = &mace_get_stats;    dev->set_multicast_list = &set_multicast_list;    ether_setup(dev);    init_dev_name(dev, lp->node);    dev->open = &mace_open;    dev->stop = &mace_close;#ifdef HAVE_TX_TIMEOUT    dev->tx_timeout = mace_tx_timeout;    dev->watchdog_timeo = TX_TIMEOUT;#endif    /* Register with Card Services */    link->next = dev_list;    dev_list = link;    client_reg.dev_info = &dev_info;    client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;    client_reg.EventMask =	CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |	CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |	CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;    client_reg.event_handler = &nmclan_event;    client_reg.Version = 0x0210;    client_reg.event_callback_args.client_data = link;    ret = CardServices(RegisterClient, &link->handle, &client_reg);    if (ret != 0) {	cs_error(link->handle, RegisterClient, ret);	nmclan_detach(link);	return NULL;    }    return link;} /* nmclan_attach *//* ----------------------------------------------------------------------------nmclan_detach	This deletes a driver "instance".  The device is de-registered	with Card Services.  If it has been released, all local data	structures are freed.  Otherwise, the structures will be freed	when the device is released.---------------------------------------------------------------------------- */static void nmclan_detach(dev_link_t *link){    mace_private *lp = link->priv;    dev_link_t **linkp;    DEBUG(0, "nmclan_detach(0x%p)\n", link);    /* Locate device structure */    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)	if (*linkp == link) break;    if (*linkp == NULL)	return;    del_timer(&link->release);    if (link->state & DEV_CONFIG) {	nmclan_release((u_long)link);	if (link->state & DEV_STALE_CONFIG) {	    link->state |= DEV_STALE_LINK;	    return;	}    }    if (link->handle)	CardServices(DeregisterClient, link->handle);    /* Unlink device structure, free bits */    *linkp = link->next;    if (link->dev)	unregister_netdev(&lp->dev);    kfree(lp);} /* nmclan_detach *//* ----------------------------------------------------------------------------mace_read	Reads a MACE register.  This is bank independent; however, the	caller must ensure that this call is not interruptable.  We are	assuming that during normal operation, the MACE is always in	bank 0.---------------------------------------------------------------------------- */static int mace_read(ioaddr_t ioaddr, int reg){  int data = 0xFF;  unsigned long flags;  switch (reg >> 4) {    case 0: /* register 0-15 */      data = inb(ioaddr + AM2150_MACE_BASE + reg);      break;    case 1: /* register 16-31 */      save_flags(flags);      cli();      MACEBANK(1);      data = inb(ioaddr + AM2150_MACE_BASE + (reg & 0x0F));      MACEBANK(0);      restore_flags(flags);      break;  }  return (data & 0xFF);} /* mace_read *//* ----------------------------------------------------------------------------mace_write	Writes to a MACE register.  This is bank independent; however,	the caller must ensure that this call is not interruptable.  We	are assuming that during normal operation, the MACE is always in	bank 0.---------------------------------------------------------------------------- */static void mace_write(ioaddr_t ioaddr, int reg, int data){  unsigned long flags;  switch (reg >> 4) {    case 0: /* register 0-15 */      outb(data & 0xFF, ioaddr + AM2150_MACE_BASE + reg);      break;    case 1: /* register 16-31 */      save_flags(flags);      cli();      MACEBANK(1);      outb(data & 0xFF, ioaddr + AM2150_MACE_BASE + (reg & 0x0F));      MACEBANK(0);      restore_flags(flags);      break;  }} /* mace_write *//* ----------------------------------------------------------------------------mace_init	Resets the MACE chip.---------------------------------------------------------------------------- */static void mace_init(ioaddr_t ioaddr, char *enet_addr){  int i;  /* MACE Software reset */  mace_write(ioaddr, MACE_BIUCC, 1);  while (mace_read(ioaddr, MACE_BIUCC) & 0x01) {    /* Wait for reset bit to be cleared automatically after <= 200ns */;  }  mace_write(ioaddr, MACE_BIUCC, 0);  /* The Am2150 requires that the MACE FIFOs operate in burst mode. */  mace_write(ioaddr, MACE_FIFOCC, 0x0F);  mace_write(ioaddr, MACE_RCVFC, 0); /* Disable Auto Strip Receive */  mace_write(ioaddr, MACE_IMR, 0xFF); /* Disable all interrupts until _open */  /*   * Bit 2-1 PORTSEL[1-0] Port Select.   * 00 AUI/10Base-2   * 01 10Base-T   * 10 DAI Port (reserved in Am2150)   * 11 GPSI   * For this card, only the first two are valid.   * So, PLSCC should be set to   * 0x00 for 10Base-2   * 0x02 for 10Base-T   * Or just set ASEL in PHYCC below!   */  switch (if_port) {    case 1:      mace_write(ioaddr, MACE_PLSCC, 0x02);      break;    case 2:      mace_write(ioaddr, MACE_PLSCC, 0x00);      break;    default:      mace_write(ioaddr, MACE_PHYCC, /* ASEL */ 4);      /* ASEL Auto Select.  When set, the PORTSEL[1-0] bits are overridden,	 and the MACE device will automatically select the operating media	 interface port. */      break;  }  mace_write(ioaddr, MACE_IAC, MACE_IAC_ADDRCHG | MACE_IAC_PHYADDR);  /* Poll ADDRCHG bit */  while (mace_read(ioaddr, MACE_IAC) & MACE_IAC_ADDRCHG)    ;  /* Set PADR register */  for (i = 0; i < ETHER_ADDR_LEN; i++)    mace_write(ioaddr, MACE_PADR, enet_addr[i]);  /* MAC Configuration Control Register should be written last */  /* Let set_multicast_list set this. */  /* mace_write(ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV); */  mace_write(ioaddr, MACE_MACCC, 0x00);} /* mace_init *//* ----------------------------------------------------------------------------nmclan_config	This routine is scheduled to run after a CARD_INSERTION event	is received, to configure the PCMCIA socket, and to make the	ethernet device available to the system.---------------------------------------------------------------------------- */#define CS_CHECK(fn, args...) \while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failedstatic void nmclan_config(dev_link_t *link){  client_handle_t handle = link->handle;  mace_private *lp = link->priv;  struct net_device *dev = &lp->dev;  tuple_t tuple;  cisparse_t parse;  u_char buf[64];  int i, last_ret, last_fn;  ioaddr_t ioaddr;  DEBUG(0, "nmclan_config(0x%p)\n", link);  tuple.Attributes = 0;  tuple.TupleData = buf;  tuple.TupleDataMax = 64;  tuple.TupleOffset = 0;  tuple.DesiredTuple = CISTPL_CONFIG;  CS_CHECK(GetFirstTuple, handle, &tuple);  CS_CHECK(GetTupleData, handle, &tuple);  CS_CHECK(ParseTuple, handle, &tuple, &parse);  link->conf.ConfigBase = parse.config.base;  /* Configure card */  link->state |= DEV_CONFIG;  CS_CHECK(RequestIO, handle, &link->io);  CS_CHECK(RequestIRQ, handle, &link->irq);  CS_CHECK(RequestConfiguration, handle, &link->conf);  dev->irq = link->irq.AssignedIRQ;  dev->base_addr = link->io.BasePort1;  i = register_netdev(dev);  if (i != 0) {    printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n");    goto failed;  }  ioaddr = dev->base_addr;  /* Read the ethernet address from the CIS. */  tuple.DesiredTuple = 0x80 /* CISTPL_CFTABLE_ENTRY_MISC */;  tuple.TupleData = buf;  tuple.TupleDataMax = 64;  tuple.TupleOffset = 0;  CS_CHECK(GetFirstTuple, handle, &tuple);  CS_CHECK(GetTupleData, handle, &tuple);  memcpy(dev->dev_addr, tuple.TupleData, ETHER_ADDR_LEN);  /* Verify configuration by reading the MACE ID. */  {    char sig[2];    sig[0] = mace_read(ioaddr, MACE_CHIPIDL);    sig[1] = mace_read(ioaddr, MACE_CHIPIDH);    if ((sig[0] == 0x40) && ((sig[1] & 0x0F) == 0x09)) {      DEBUG(0, "nmclan_cs configured: mace id=%x %x\n",	    sig[0], sig[1]);    } else {      printk(KERN_NOTICE "nmclan_cs: mace id not found: %x %x should"	     " be 0x40 0x?9\n", sig[0], sig[1]);      link->state &= ~DEV_CONFIG_PENDING;      return;    }  }  mace_init(ioaddr, dev->dev_addr);  /* The if_port symbol can be set when the module is loaded */  if (if_port <= 2)    dev->if_port = if_port;  else    printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n");#if 0  /* Determine which port we are using if auto is selected */  if (if_port==0) {    mace_write(ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV);    DEBUG(2, "%s: mace_phycc 0x%X.\n", dev->name,	  mace_read(ioaddr, MACE_PHYCC));    if (mace_read(ioaddr, MACE_PHYCC) & MACE_PHYCC_LNKFL)      /* 10base-T receiver is in link fail, MACE is using AUI port. */      dev->if_port = 2;    else      dev->if_port = 1;    mace_write(ioaddr, MACE_MACCC, 0x00);  }  /* Unfortunately, this doesn't seem to work.  LNKFL is always set.     LNKFL is supposed to be opposite the green LED on the edge of the card.     It doesn't work if it is checked and printed in _open() either.     It does work if check in _start_xmit(), but that's not a good place     to printk. */#endif  copy_dev_name(lp->node, dev);  link->dev = &lp->node;  link->state &= ~DEV_CONFIG_PENDING;  printk(KERN_INFO "%s: nmclan: port %#3lx, irq %d, %s port, hw_addr ",	 dev->name, dev->base_addr, dev->irq, if_names[dev->if_port]);  for (i = 0; i < 6; i++)      printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));  return;cs_failed:    cs_error(link->handle, last_fn, last_ret);failed:    nmclan_release((u_long)link);    link->state &= ~DEV_CONFIG_PENDING;    return;} /* nmclan_config *//* ----------------------------------------------------------------------------nmclan_release	After a card is removed, nmclan_release() will unregister the	net device, and release the PCMCIA configuration.  If the device	is still open, this will be postponed until it is closed.---------------------------------------------------------------------------- */static void nmclan_release(u_long arg){  dev_link_t *link = (dev_link_t *)arg;  DEBUG(0, "nmclan_release(0x%p)\n", link);  if (link->open) {    DEBUG(1, "nmclan_cs: release postponed, '%s' "	  "still open\n", link->dev->dev_name);    link->state |= DEV_STALE_CONFIG;    return;  }  CardServices(ReleaseConfiguration, link->handle);  CardServices(ReleaseIO, link->handle, &link->io);  CardServices(ReleaseIRQ, link->handle, &link->irq);  link->state &= ~DEV_CONFIG;} /* nmclan_release *//* ----------------------------------------------------------------------------nmclan_event	The card status event handler.  Mostly, this schedules other	stuff to run after an event is received.  A CARD_REMOVAL event	also sets some flags to discourage the net drivers from trying	to talk to the card any more.---------------------------------------------------------------------------- */static int nmclan_event(event_t event, int priority,		       event_callback_args_t *args){  dev_link_t *link = args->client_data;  mace_private *lp = link->priv;  struct net_device *dev = &lp->dev;  DEBUG(1, "nmclan_event(0x%06x)\n", event);  switch (event) {    case CS_EVENT_CARD_REMOVAL:      link->state &= ~DEV_PRESENT;      if (link->state & DEV_CONFIG) {

⌨️ 快捷键说明

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