📄 ibmtr_cs.c
字号:
struct tok_info *ti = netdev_priv(dev); tuple_t tuple; cisparse_t parse; win_req_t req; memreq_t mem; int i, last_ret, last_fn; u_char buf[64]; DEBUG(0, "ibmtr_config(0x%p)\n", link); tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_CONFIG; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; /* Configure card */ link->state |= DEV_CONFIG; link->conf.ConfigIndex = 0x61; /* Determine if this is PRIMARY or ALTERNATE. */ /* Try PRIMARY card at 0xA20-0xA23 */ link->io.BasePort1 = 0xA20; i = pcmcia_request_io(link->handle, &link->io); if (i != CS_SUCCESS) { /* Couldn't get 0xA20-0xA23. Try ALTERNATE at 0xA24-0xA27. */ link->io.BasePort1 = 0xA24; CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io)); } dev->base_addr = link->io.BasePort1; CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); dev->irq = link->irq.AssignedIRQ; ti->irq = link->irq.AssignedIRQ; ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq); /* Allocate the MMIO memory window */ req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; req.Attributes |= WIN_USE_WAIT; req.Base = 0; req.Size = 0x2000; req.AccessSpeed = 250; CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win)); mem.CardOffset = mmiobase; mem.Page = 0; CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); ti->mmio = ioremap(req.Base, req.Size); /* Allocate the SRAM memory window */ req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; req.Attributes |= WIN_USE_WAIT; req.Base = 0; req.Size = sramsize * 1024; req.AccessSpeed = 250; CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &info->sram_win_handle)); mem.CardOffset = srambase; mem.Page = 0; CS_CHECK(MapMemPage, pcmcia_map_mem_page(info->sram_win_handle, &mem)); ti->sram_base = mem.CardOffset >> 12; ti->sram_virt = ioremap(req.Base, req.Size); ti->sram_phys = req.Base; CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); /* Set up the Token-Ring Controller Configuration Register and turn on the card. Check the "Local Area Network Credit Card Adapters Technical Reference" SC30-3585 for this info. */ ibmtr_hw_setup(dev, mmiobase); link->dev = &info->node; link->state &= ~DEV_CONFIG_PENDING; SET_NETDEV_DEV(dev, &handle_to_dev(handle)); i = ibmtr_probe_card(dev); if (i != 0) { printk(KERN_NOTICE "ibmtr_cs: register_netdev() failed\n"); link->dev = NULL; goto failed; } strcpy(info->node.dev_name, dev->name); printk(KERN_INFO "%s: port %#3lx, irq %d,", dev->name, dev->base_addr, dev->irq); printk (" mmio %#5lx,", (u_long)ti->mmio); printk (" sram %#5lx,", (u_long)ti->sram_base << 12); printk ("\n" KERN_INFO " hwaddr="); for (i = 0; i < TR_ALEN; i++) printk("%02X", dev->dev_addr[i]); printk("\n"); return;cs_failed: cs_error(link->handle, last_fn, last_ret);failed: ibmtr_release(link);} /* ibmtr_config *//*====================================================================== After a card is removed, ibmtr_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 ibmtr_release(dev_link_t *link){ ibmtr_dev_t *info = link->priv; struct net_device *dev = info->dev; DEBUG(0, "ibmtr_release(0x%p)\n", link); pcmcia_release_configuration(link->handle); pcmcia_release_io(link->handle, &link->io); pcmcia_release_irq(link->handle, &link->irq); if (link->win) { struct tok_info *ti = netdev_priv(dev); iounmap(ti->mmio); pcmcia_release_window(link->win); pcmcia_release_window(info->sram_win_handle); } link->state &= ~DEV_CONFIG;}/*====================================================================== 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 ibmtr_event(event_t event, int priority, event_callback_args_t *args){ dev_link_t *link = args->client_data; ibmtr_dev_t *info = link->priv; struct net_device *dev = info->dev; DEBUG(1, "ibmtr_event(0x%06x)\n", event); switch (event) { case CS_EVENT_CARD_REMOVAL: link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG) { /* set flag to bypass normal interrupt code */ struct tok_info *priv = netdev_priv(dev); priv->sram_phys |= 1; netif_device_detach(dev); } break; case CS_EVENT_CARD_INSERTION: link->state |= DEV_PRESENT; ibmtr_config(link); break; case CS_EVENT_PM_SUSPEND: link->state |= DEV_SUSPEND; /* Fall through... */ case CS_EVENT_RESET_PHYSICAL: if (link->state & DEV_CONFIG) { if (link->open) netif_device_detach(dev); pcmcia_release_configuration(link->handle); } break; case CS_EVENT_PM_RESUME: link->state &= ~DEV_SUSPEND; /* Fall through... */ case CS_EVENT_CARD_RESET: if (link->state & DEV_CONFIG) { pcmcia_request_configuration(link->handle, &link->conf); if (link->open) { ibmtr_probe(dev); /* really? */ netif_device_attach(dev); } } break; } return 0;} /* ibmtr_event *//*====================================================================*/static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase){ int i; /* Bizarre IBM behavior, there are 16 bits of information we need to set, but the card only allows us to send 4 bits at a time. For each byte sent to base_addr, bits 7-4 tell the card which part of the 16 bits we are setting, bits 3-0 contain the actual information */ /* First nibble provides 4 bits of mmio */ i = (mmiobase >> 16) & 0x0F; outb(i, dev->base_addr); /* Second nibble provides 3 bits of mmio */ i = 0x10 | ((mmiobase >> 12) & 0x0E); outb(i, dev->base_addr); /* Third nibble, hard-coded values */ i = 0x26; outb(i, dev->base_addr); /* Fourth nibble sets shared ram page size */ /* 8 = 00, 16 = 01, 32 = 10, 64 = 11 */ i = (sramsize >> 4) & 0x07; i = ((i == 4) ? 3 : i) << 2; i |= 0x30; if (ringspeed == 16) i |= 2; if (dev->base_addr == 0xA24) i |= 1; outb(i, dev->base_addr); /* 0x40 will release the card for use */ outb(0x40, dev->base_addr); return;}static struct pcmcia_device_id ibmtr_ids[] = { PCMCIA_DEVICE_PROD_ID12("3Com", "TokenLink Velocity PC Card", 0x41240e5b, 0x82c3734e), PCMCIA_DEVICE_PROD_ID12("IBM", "TOKEN RING", 0xb569a6e5, 0xbf8eed47), PCMCIA_DEVICE_NULL,};MODULE_DEVICE_TABLE(pcmcia, ibmtr_ids);static struct pcmcia_driver ibmtr_cs_driver = { .owner = THIS_MODULE, .drv = { .name = "ibmtr_cs", }, .attach = ibmtr_attach, .event = ibmtr_event, .detach = ibmtr_detach, .id_table = ibmtr_ids,};static int __init init_ibmtr_cs(void){ return pcmcia_register_driver(&ibmtr_cs_driver);}static void __exit exit_ibmtr_cs(void){ pcmcia_unregister_driver(&ibmtr_cs_driver); BUG_ON(dev_list != NULL);}module_init(init_ibmtr_cs);module_exit(exit_ibmtr_cs);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -