11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================== 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds A PCMCIA token-ring driver for IBM-based cards 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This driver supports the IBM PCMCIA Token-Ring Card. 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Written by Steve Kipisz, kipisz@vnet.ibm.com or 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bungy@ibm.net 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Written 1995,1996. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This code is based on pcnet_cs.c from David Hinds. 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V2.2.0 February 1999 - Mike Phillips phillim@amtrak.com 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Linux V2.2.x presented significant changes to the underlying 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ibmtr.c code. Mainly the code became a lot more organized and 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds modular. 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This caused the old PCMCIA Token Ring driver to give up and go 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds home early. Instead of just patching the old code to make it 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds work, the PCMCIA code has been streamlined, updated and possibly 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds improved. 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This code now only contains code required for the Card Services. 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds All we do here is set the card up enough so that the real ibmtr.c 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds driver can find it and work with it properly. 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i.e. We set up the io port, irq, mmio memory and shared ram 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memory. This enables ibmtr_probe in ibmtr.c to find the card and 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds configure it as though it was a normal ISA and/or PnP card. 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CHANGES 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds v2.2.5 April 1999 Mike Phillips (phillim@amtrak.com) 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Obscure bug fix, required changed to ibmtr.c not ibmtr_cs.c 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds v2.2.7 May 1999 Mike Phillips (phillim@amtrak.com) 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Updated to version 2.2.7 to match the first version of the kernel 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds that the modification to ibmtr.c were incorporated into. 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds v2.2.17 July 2000 Burt Silverman (burts@us.ibm.com) 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Address translation feature of PCMCIA controller is usable so 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memory windows can be placed in High memory (meaning above 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0xFFFFF.) 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds======================================================================*/ 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 48636b8116d4e116eca1ac978f546b16fadfc15a6cJoe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 49636b8116d4e116eca1ac978f546b16fadfc15a6cJoe Perches 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ptrace.h> 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h> 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h> 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/trdevice.h> 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ibmtr.h> 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/cistpl.h> 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pcmcia/ds.h> 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PCMCIA 68c0153225a0e86013b8b8267ffd94e5484d83b916Jeff Kirsher#include "ibmtr.c" 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Parameters that can be set with 'insmod' */ 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* MMIO base address */ 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u_long mmiobase = 0xce000; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* SRAM base address */ 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u_long srambase = 0xd0000; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* SRAM size 8,16,32,64 */ 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u_long sramsize = 64; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Ringspeed 4,16 */ 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ringspeed = 16; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(mmiobase, ulong, 0); 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(srambase, ulong, 0); 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(sramsize, ulong, 0); 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(ringspeed, int, 0); 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9515b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowskistatic int ibmtr_config(struct pcmcia_device *link); 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase); 97fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowskistatic void ibmtr_release(struct pcmcia_device *link); 98cc3b4866bee996c922e875b8c8efe9f0d8803aaeDominik Brodowskistatic void ibmtr_detach(struct pcmcia_device *p_dev); 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct ibmtr_dev_t { 103fd238232cd0ff4840ae6946bb338502154096d88Dominik Brodowski struct pcmcia_device *p_dev; 104cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski struct net_device *dev; 105cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski struct tok_info *ti; 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} ibmtr_dev_t; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1085fa9167a1bf5f5a4b7282f5e7ac56a4a5a1fa044Dominik Brodowskistatic irqreturn_t ibmtr_interrupt(int irq, void *dev_id) { 1095fa9167a1bf5f5a4b7282f5e7ac56a4a5a1fa044Dominik Brodowski ibmtr_dev_t *info = dev_id; 1105fa9167a1bf5f5a4b7282f5e7ac56a4a5a1fa044Dominik Brodowski struct net_device *dev = info->dev; 1115fa9167a1bf5f5a4b7282f5e7ac56a4a5a1fa044Dominik Brodowski return tok_interrupt(irq, dev); 1125fa9167a1bf5f5a4b7282f5e7ac56a4a5a1fa044Dominik Brodowski}; 1135fa9167a1bf5f5a4b7282f5e7ac56a4a5a1fa044Dominik Brodowski 114abf0437b420b1476b9afd56af69d1a725f51359cAl Virostatic int __devinit ibmtr_attach(struct pcmcia_device *link) 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ibmtr_dev_t *info; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev; 118fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski 119dd0fab5b940c0b65f26ac5b01485bac1f690ace6Dominik Brodowski dev_dbg(&link->dev, "ibmtr_attach()\n"); 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Create new token-ring device */ 122dd00cc486ab1c17049a535413d1751ef3482141cYoann Padioleau info = kzalloc(sizeof(*info), GFP_KERNEL); 123f8cfa618dccbdc6dab5297f75779566a388a98fdDominik Brodowski if (!info) return -ENOMEM; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev = alloc_trdev(sizeof(struct tok_info)); 125f8cfa618dccbdc6dab5297f75779566a388a98fdDominik Brodowski if (!dev) { 126f8cfa618dccbdc6dab5297f75779566a388a98fdDominik Brodowski kfree(info); 127f8cfa618dccbdc6dab5297f75779566a388a98fdDominik Brodowski return -ENOMEM; 128f8cfa618dccbdc6dab5297f75779566a388a98fdDominik Brodowski } 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 130fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski info->p_dev = link; 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds link->priv = info; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->ti = netdev_priv(dev); 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13490abdc3b973229bae98dd96649d9f7106cc177a4Dominik Brodowski link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; 13590abdc3b973229bae98dd96649d9f7106cc177a4Dominik Brodowski link->resource[0]->end = 4; 1361ac71e5a35eebee60cdcf15b3980bd94498f037bDominik Brodowski link->config_flags |= CONF_ENABLE_IRQ; 1377feabb6412ea23edd298c0fa90e5aa6733eb4a42Dominik Brodowski link->config_regs = PRESENT_OPTION; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1395fa9167a1bf5f5a4b7282f5e7ac56a4a5a1fa044Dominik Brodowski info->dev = dev; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14115b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return ibmtr_config(link); 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* ibmtr_attach */ 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 144fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowskistatic void ibmtr_detach(struct pcmcia_device *link) 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ibmtr_dev_t *info = link->priv; 147b463581154f3f3eecda27cae60df813fefcd84d3Dominik Brodowski struct net_device *dev = info->dev; 1485bebf82fff53a96f330c0879ffe870bdf3aaeab6Paul Walmsley struct tok_info *ti = netdev_priv(dev); 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 150dd0fab5b940c0b65f26ac5b01485bac1f690ace6Dominik Brodowski dev_dbg(&link->dev, "ibmtr_detach\n"); 1515bebf82fff53a96f330c0879ffe870bdf3aaeab6Paul Walmsley 1525bebf82fff53a96f330c0879ffe870bdf3aaeab6Paul Walmsley /* 1535bebf82fff53a96f330c0879ffe870bdf3aaeab6Paul Walmsley * When the card removal interrupt hits tok_interrupt(), 1545bebf82fff53a96f330c0879ffe870bdf3aaeab6Paul Walmsley * bail out early, so we don't crash the machine 1555bebf82fff53a96f330c0879ffe870bdf3aaeab6Paul Walmsley */ 1565bebf82fff53a96f330c0879ffe870bdf3aaeab6Paul Walmsley ti->sram_phys |= 1; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 158c7c2fa079073ab92b0736a161b4cf1051a3e631fDominik Brodowski unregister_netdev(dev); 1595bebf82fff53a96f330c0879ffe870bdf3aaeab6Paul Walmsley 1605bebf82fff53a96f330c0879ffe870bdf3aaeab6Paul Walmsley del_timer_sync(&(ti->tr_timer)); 161e2d4096365e06b9a3799afbadc28b4519c0b3526Dominik Brodowski 162e2d4096365e06b9a3799afbadc28b4519c0b3526Dominik Brodowski ibmtr_release(link); 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_netdev(dev); 165b463581154f3f3eecda27cae60df813fefcd84d3Dominik Brodowski kfree(info); 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* ibmtr_detach */ 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 168abf0437b420b1476b9afd56af69d1a725f51359cAl Virostatic int __devinit ibmtr_config(struct pcmcia_device *link) 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ibmtr_dev_t *info = link->priv; 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = info->dev; 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct tok_info *ti = netdev_priv(dev); 173dd0fab5b940c0b65f26ac5b01485bac1f690ace6Dominik Brodowski int i, ret; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 175dd0fab5b940c0b65f26ac5b01485bac1f690ace6Dominik Brodowski dev_dbg(&link->dev, "ibmtr_config\n"); 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17790abdc3b973229bae98dd96649d9f7106cc177a4Dominik Brodowski link->io_lines = 16; 1787feabb6412ea23edd298c0fa90e5aa6733eb4a42Dominik Brodowski link->config_index = 0x61; 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Determine if this is PRIMARY or ALTERNATE. */ 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Try PRIMARY card at 0xA20-0xA23 */ 18390abdc3b973229bae98dd96649d9f7106cc177a4Dominik Brodowski link->resource[0]->start = 0xA20; 18490abdc3b973229bae98dd96649d9f7106cc177a4Dominik Brodowski i = pcmcia_request_io(link); 1854c89e88bfde6a3c179790e21004f24e09a058290Dominik Brodowski if (i != 0) { 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Couldn't get 0xA20-0xA23. Try ALTERNATE at 0xA24-0xA27. */ 18790abdc3b973229bae98dd96649d9f7106cc177a4Dominik Brodowski link->resource[0]->start = 0xA24; 18890abdc3b973229bae98dd96649d9f7106cc177a4Dominik Brodowski ret = pcmcia_request_io(link); 189dd0fab5b940c0b65f26ac5b01485bac1f690ace6Dominik Brodowski if (ret) 190dd0fab5b940c0b65f26ac5b01485bac1f690ace6Dominik Brodowski goto failed; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1929a017a910346afd88ec2e065989903bf211a7d37Dominik Brodowski dev->base_addr = link->resource[0]->start; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 194eb14120f743d29744d9475bffec56ff4ad43a749Dominik Brodowski ret = pcmcia_request_exclusive_irq(link, ibmtr_interrupt); 195dd0fab5b940c0b65f26ac5b01485bac1f690ace6Dominik Brodowski if (ret) 196dd0fab5b940c0b65f26ac5b01485bac1f690ace6Dominik Brodowski goto failed; 197eb14120f743d29744d9475bffec56ff4ad43a749Dominik Brodowski dev->irq = link->irq; 198eb14120f743d29744d9475bffec56ff4ad43a749Dominik Brodowski ti->irq = link->irq; 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Allocate the MMIO memory window */ 202cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski link->resource[2]->flags |= WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; 203cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski link->resource[2]->flags |= WIN_USE_WAIT; 204cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski link->resource[2]->start = 0; 205cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski link->resource[2]->end = 0x2000; 206cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski ret = pcmcia_request_window(link, link->resource[2], 250); 207dd0fab5b940c0b65f26ac5b01485bac1f690ace6Dominik Brodowski if (ret) 208dd0fab5b940c0b65f26ac5b01485bac1f690ace6Dominik Brodowski goto failed; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 210cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski ret = pcmcia_map_mem_page(link, link->resource[2], mmiobase); 211dd0fab5b940c0b65f26ac5b01485bac1f690ace6Dominik Brodowski if (ret) 212dd0fab5b940c0b65f26ac5b01485bac1f690ace6Dominik Brodowski goto failed; 213cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski ti->mmio = ioremap(link->resource[2]->start, 214cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski resource_size(link->resource[2])); 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Allocate the SRAM memory window */ 217cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski link->resource[3]->flags = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; 218cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski link->resource[3]->flags |= WIN_USE_WAIT; 219cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski link->resource[3]->start = 0; 220cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski link->resource[3]->end = sramsize * 1024; 221cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski ret = pcmcia_request_window(link, link->resource[3], 250); 222dd0fab5b940c0b65f26ac5b01485bac1f690ace6Dominik Brodowski if (ret) 223dd0fab5b940c0b65f26ac5b01485bac1f690ace6Dominik Brodowski goto failed; 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 225cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski ret = pcmcia_map_mem_page(link, link->resource[3], srambase); 226dd0fab5b940c0b65f26ac5b01485bac1f690ace6Dominik Brodowski if (ret) 227dd0fab5b940c0b65f26ac5b01485bac1f690ace6Dominik Brodowski goto failed; 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 229b5cb259e7fac5536c4ddf350af6a3d6cc950e47eDominik Brodowski ti->sram_base = srambase >> 12; 230cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski ti->sram_virt = ioremap(link->resource[3]->start, 231cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski resource_size(link->resource[3])); 232cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski ti->sram_phys = link->resource[3]->start; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2341ac71e5a35eebee60cdcf15b3980bd94498f037bDominik Brodowski ret = pcmcia_enable_device(link); 235dd0fab5b940c0b65f26ac5b01485bac1f690ace6Dominik Brodowski if (ret) 236dd0fab5b940c0b65f26ac5b01485bac1f690ace6Dominik Brodowski goto failed; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set up the Token-Ring Controller Configuration Register and 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds turn on the card. Check the "Local Area Network Credit Card 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Adapters Technical Reference" SC30-3585 for this info. */ 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ibmtr_hw_setup(dev, mmiobase); 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 243dd2e5a156525f11754d9b1e0583f6bb49c253d62Dominik Brodowski SET_NETDEV_DEV(dev, &link->dev); 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = ibmtr_probe_card(dev); 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i != 0) { 247636b8116d4e116eca1ac978f546b16fadfc15a6cJoe Perches pr_notice("register_netdev() failed\n"); 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed; 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 251636b8116d4e116eca1ac978f546b16fadfc15a6cJoe Perches netdev_info(dev, "port %#3lx, irq %d, mmio %#5lx, sram %#5lx, hwaddr=%pM\n", 252636b8116d4e116eca1ac978f546b16fadfc15a6cJoe Perches dev->base_addr, dev->irq, 253636b8116d4e116eca1ac978f546b16fadfc15a6cJoe Perches (u_long)ti->mmio, (u_long)(ti->sram_base << 12), 254636b8116d4e116eca1ac978f546b16fadfc15a6cJoe Perches dev->dev_addr); 25515b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return 0; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfailed: 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ibmtr_release(link); 25915b99ac1729503db9e6dc642a50b9b6cb3bf51f9Dominik Brodowski return -ENODEV; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} /* ibmtr_config */ 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 262fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowskistatic void ibmtr_release(struct pcmcia_device *link) 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2645f2a71fcb7995633b335a1e380ac63a968e61320Dominik Brodowski ibmtr_dev_t *info = link->priv; 2655f2a71fcb7995633b335a1e380ac63a968e61320Dominik Brodowski struct net_device *dev = info->dev; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 267dd0fab5b940c0b65f26ac5b01485bac1f690ace6Dominik Brodowski dev_dbg(&link->dev, "ibmtr_release\n"); 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 269cdb138080b78146d1cdadba9f5dadbeb97445b91Dominik Brodowski if (link->resource[2]->end) { 2705f2a71fcb7995633b335a1e380ac63a968e61320Dominik Brodowski struct tok_info *ti = netdev_priv(dev); 2715f2a71fcb7995633b335a1e380ac63a968e61320Dominik Brodowski iounmap(ti->mmio); 2725f2a71fcb7995633b335a1e380ac63a968e61320Dominik Brodowski } 273fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowski pcmcia_disable_device(link); 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 276fba395eee7d3f342ca739c20f5b3ee635d0420a0Dominik Brodowskistatic int ibmtr_suspend(struct pcmcia_device *link) 27798e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski{ 27898e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski ibmtr_dev_t *info = link->priv; 27998e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski struct net_device *dev = info->dev; 28098e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski 281e2d4096365e06b9a3799afbadc28b4519c0b3526Dominik Brodowski if (link->open) 2828661bb5b4af1849c1f5a4e80c4e275fd13c155d6Dominik Brodowski netif_device_detach(dev); 28398e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski 28498e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski return 0; 28598e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski} 28698e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski 2878814b5050d183f00a25a087b550841797c0c2775Al Virostatic int __devinit ibmtr_resume(struct pcmcia_device *link) 28898e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski{ 28998e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski ibmtr_dev_t *info = link->priv; 29098e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski struct net_device *dev = info->dev; 29198e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski 292e2d4096365e06b9a3799afbadc28b4519c0b3526Dominik Brodowski if (link->open) { 2938661bb5b4af1849c1f5a4e80c4e275fd13c155d6Dominik Brodowski ibmtr_probe(dev); /* really? */ 2948661bb5b4af1849c1f5a4e80c4e275fd13c155d6Dominik Brodowski netif_device_attach(dev); 2958661bb5b4af1849c1f5a4e80c4e275fd13c155d6Dominik Brodowski } 29698e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski 29798e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski return 0; 29898e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski} 29998e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski 30098e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*====================================================================*/ 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase) 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Bizarre IBM behavior, there are 16 bits of information we 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds need to set, but the card only allows us to send 4 bits at a 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds time. For each byte sent to base_addr, bits 7-4 tell the 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card which part of the 16 bits we are setting, bits 3-0 contain 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the actual information */ 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* First nibble provides 4 bits of mmio */ 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = (mmiobase >> 16) & 0x0F; 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(i, dev->base_addr); 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Second nibble provides 3 bits of mmio */ 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = 0x10 | ((mmiobase >> 12) & 0x0E); 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(i, dev->base_addr); 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Third nibble, hard-coded values */ 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = 0x26; 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(i, dev->base_addr); 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Fourth nibble sets shared ram page size */ 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8 = 00, 16 = 01, 32 = 10, 64 = 11 */ 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = (sramsize >> 4) & 0x07; 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = ((i == 4) ? 3 : i) << 2; 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i |= 0x30; 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ringspeed == 16) 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i |= 2; 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->base_addr == 0xA24) 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i |= 1; 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(i, dev->base_addr); 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 0x40 will release the card for use */ 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x40, dev->base_addr); 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34225f8f54f6e178acfd503a95441b0ea05c525f751Joe Perchesstatic const struct pcmcia_device_id ibmtr_ids[] = { 343469bf2b9389c9265ac0920da5b1a5c71fe496213Dominik Brodowski PCMCIA_DEVICE_PROD_ID12("3Com", "TokenLink Velocity PC Card", 0x41240e5b, 0x82c3734e), 344469bf2b9389c9265ac0920da5b1a5c71fe496213Dominik Brodowski PCMCIA_DEVICE_PROD_ID12("IBM", "TOKEN RING", 0xb569a6e5, 0xbf8eed47), 345469bf2b9389c9265ac0920da5b1a5c71fe496213Dominik Brodowski PCMCIA_DEVICE_NULL, 346469bf2b9389c9265ac0920da5b1a5c71fe496213Dominik Brodowski}; 347469bf2b9389c9265ac0920da5b1a5c71fe496213Dominik BrodowskiMODULE_DEVICE_TABLE(pcmcia, ibmtr_ids); 348469bf2b9389c9265ac0920da5b1a5c71fe496213Dominik Brodowski 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pcmcia_driver ibmtr_cs_driver = { 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 3512e9b981a7c63ee8278df6823f8389d69dad1a499Dominik Brodowski .name = "ibmtr_cs", 352f8cfa618dccbdc6dab5297f75779566a388a98fdDominik Brodowski .probe = ibmtr_attach, 353cc3b4866bee996c922e875b8c8efe9f0d8803aaeDominik Brodowski .remove = ibmtr_detach, 354469bf2b9389c9265ac0920da5b1a5c71fe496213Dominik Brodowski .id_table = ibmtr_ids, 35598e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski .suspend = ibmtr_suspend, 35698e4c28b7ec390c2dad6a4c69d69629c0f7e8b10Dominik Brodowski .resume = ibmtr_resume, 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init init_ibmtr_cs(void) 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return pcmcia_register_driver(&ibmtr_cs_driver); 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit exit_ibmtr_cs(void) 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcmcia_unregister_driver(&ibmtr_cs_driver); 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(init_ibmtr_cs); 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(exit_ibmtr_cs); 371