📄 ibmtr_cs.c
字号:
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; link->conf.ConfigIndex = 0x61; /* Determine if this is PRIMARY or ALTERNATE. */ /* Try PRIMARY card at 0xA20-0xA23 */ link->io.BasePort1 = 0xA20; i = CardServices(RequestIO, link->handle, &link->io); if (i == CS_SUCCESS) { memcpy(info->node.dev_name, "tr0\0", 4); } else { /* Couldn't get 0xA20-0xA23. Try ALTERNATE at 0xA24-0xA27. */ link->io.BasePort1 = 0xA24; CS_CHECK(RequestIO, link->handle, &link->io); memcpy(info->node.dev_name, "tr1\0", 4); } dev->base_addr = link->io.BasePort1; CS_CHECK(RequestIRQ, 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|(TR_OLD ? WIN_STRICT_ALIGN : 0); req.Base = (TR_OLD ? mmiobase : 0); req.Size = 0x2000; req.AccessSpeed = 250; link->win = (window_handle_t)link->handle; CS_CHECK(RequestWindow, &link->win, &req); mem.CardOffset = (TR_OLD ? req.Base : mmiobase); mem.Page = 0; CS_CHECK(MapMemPage, link->win, &mem); ti->mmio = (u_long)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|(TR_OLD ? WIN_MAP_BELOW_1MB : 0); req.Base = (TR_OLD ? srambase : 0); req.Size = sramsize * 1024; req.AccessSpeed = 250; info->sram_win_handle = (window_handle_t)link->handle; CS_CHECK(RequestWindow, &info->sram_win_handle, &req); mem.CardOffset = (TR_OLD ? req.Base : srambase); mem.Page = 0; CS_CHECK(MapMemPage, info->sram_win_handle, &mem); ti->sram_base = mem.CardOffset >> 12;#if TR_OLD ti->sram = 0;#else ti->sram_virt = (u_long)ioremap(req.Base, req.Size);#endif CS_CHECK(RequestConfiguration, 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, (TR_OLD ? (u_int)ti->mmio : mmiobase)); i = register_trdev(dev); if (i != 0) { printk(KERN_NOTICE "ibmtr_cs: register_trdev() failed\n"); goto failed; } link->dev = &info->node; 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"); link->state &= ~DEV_CONFIG_PENDING; return;cs_failed: cs_error(link->handle, last_fn, last_ret);failed: ibmtr_release((u_long)link); link->state &= ~DEV_CONFIG_PENDING;} /* 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(u_long arg){ dev_link_t *link = (dev_link_t *)arg; ibmtr_dev_t *info = link->priv; struct net_device *dev = info->dev; DEBUG(0, "ibmtr_release(0x%p)\n", link); if (link->open) { DEBUG(1, "ibmtr_cs: release postponed, '%s' " "still open\n", info->node.dev_name); link->state |= DEV_STALE_CONFIG; return; } CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIRQ, link->handle, &link->irq); if (link->win) { struct tok_info *ti = dev->priv; iounmap((void *)ti->mmio);#if !(TR_OLD) iounmap((void *)ti->sram_virt);#endif CardServices(ReleaseWindow, link->win); CardServices(ReleaseWindow, info->sram_win_handle); } link->state &= ~DEV_CONFIG;} /* ibmtr_release *//*====================================================================== 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) {#if !(TR_OLD) /* set flag to bypass normal interrupt code */ ((struct tok_info *)dev->priv)->sram_virt |= 1;#endif netif_device_detach(dev); mod_timer(&link->release, jiffies + HZ/20); } break; case CS_EVENT_CARD_INSERTION: link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; 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); CardServices(ReleaseConfiguration, link->handle); } break; case CS_EVENT_PM_RESUME: link->state &= ~DEV_SUSPEND; /* Fall through... */ case CS_EVENT_CARD_RESET: if (link->state & DEV_CONFIG) { CardServices(RequestConfiguration, link->handle, &link->conf); if (link->open) { (dev->init)(dev); netif_device_attach(dev); } } break; } return 0;} /* ibmtr_event *//*====================================================================*/static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase){#if (LINUX_VERSION_CODE < VERSION(2,2,0)) struct tok_info *ti = dev->priv;#endif 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);#if (LINUX_VERSION_CODE < VERSION(2,2,0)) /* Get hw address of token ring card */ for (i = 0; i < 12; i++) { /* Tech ref states must do this */ ti->hw_address[i] = readb(ti->mmio + AIP + i*2) & 0x0f; if (i & 1) dev->dev_addr[i>>1] |= ti->hw_address[i]; else dev->dev_addr[i>>1] = ti->hw_address[i]<<4; } /* get Adapter type: 'F' = Adapter/A, 'E' = 16/4 Adapter II,...*/ ti->adapter_type = readb(ti->mmio + AIPADAPTYPE); /* get Data Rate: F=4Mb, E=16Mb, D=4Mb & 16Mb ?? */ ti->data_rate = readb(ti->mmio + AIPDATARATE); /* Get Early Token Release support?: F=no, E=4Mb, D=16Mb, C=4&16Mb */ ti->token_release = readb(ti->mmio + AIPEARLYTOKEN); /* How much shared RAM is on adapter ? */ ti->avail_shared_ram = 64; /* for now */ /* We need to set or do a bunch of work here based on previous results.. */ /* Support paging? What sizes?: F=no, E=16k, D=32k, C=16 & 32k */ ti->shared_ram_paging = readb(ti->mmio + AIPSHRAMPAGE); /* Available DHB 4Mb size: F=2048, E=4096, D=4464 */ ti->dhb_size4mb = readb(ti->mmio + AIP4MBDHB); /* Available DHB 16Mb size: F=2048, E=4096, D=8192, C=16384, B=17960 */ ti->dhb_size16mb = readb(ti->mmio + AIP16MBDHB); /* For now, no shared ram paging */ /* determine how much of total RAM is mapped into PC space */ ti->mapped_ram_size = 1<<(((readb(ti->mmio+ ACA_OFFSET + ACA_RW + RRR_ODD))>>2)+4); ti->page_mask=0;#endif}/*====================================================================== A sweet little function that circumvents the problem with ibmtr.c trying to use more memory than we can allocate for the PCMCIA card. ibmtr.c just assumes that if a card has 64K of shared ram, the entire 64K must be mapped into memory, whereas resources are sometimes a little tight in card services so we fool ibmtr.c into thinking the card has less memory on it than it has. ======================================================================*/unsigned char pcmcia_reality_check(unsigned char gss){ return (gss < sramsize) ? sramsize : gss;}/*====================================================================*/static int __init init_ibmtr_cs(void){ servinfo_t serv; DEBUG(0, "%s", version); CardServices(GetCardServicesInfo, &serv); if (serv.Revision != CS_RELEASE_CODE) { printk(KERN_NOTICE "ibmtr_cs: Card Services release " "does not match!\n"); return -EINVAL; } register_pccard_driver(&dev_info, &ibmtr_attach, &ibmtr_detach); return 0;}static void __exit exit_ibmtr_cs(void){ DEBUG(0, "ibmtr_cs: unloading\n"); unregister_pccard_driver(&dev_info); while (dev_list != NULL) ibmtr_detach(dev_list);}module_init(init_ibmtr_cs);module_exit(exit_ibmtr_cs);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -