Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.26-rc7 465 lines 11 kB view raw
1/* 2 * abyss.c: Network driver for the Madge Smart 16/4 PCI Mk2 token ring card. 3 * 4 * Written 1999-2000 by Adam Fritzler 5 * 6 * This software may be used and distributed according to the terms 7 * of the GNU General Public License, incorporated herein by reference. 8 * 9 * This driver module supports the following cards: 10 * - Madge Smart 16/4 PCI Mk2 11 * 12 * Maintainer(s): 13 * AF Adam Fritzler 14 * 15 * Modification History: 16 * 30-Dec-99 AF Split off from the tms380tr driver. 17 * 22-Jan-00 AF Updated to use indirect read/writes 18 * 23-Nov-00 JG New PCI API, cleanups 19 * 20 * 21 * TODO: 22 * 1. See if we can use MMIO instead of inb/outb/inw/outw 23 * 2. Add support for Mk1 (has AT24 attached to the PCI 24 * config registers) 25 * 26 */ 27 28#include <linux/module.h> 29#include <linux/kernel.h> 30#include <linux/errno.h> 31#include <linux/pci.h> 32#include <linux/init.h> 33#include <linux/netdevice.h> 34#include <linux/trdevice.h> 35 36#include <asm/system.h> 37#include <asm/io.h> 38#include <asm/irq.h> 39 40#include "tms380tr.h" 41#include "abyss.h" /* Madge-specific constants */ 42 43static char version[] __devinitdata = 44"abyss.c: v1.02 23/11/2000 by Adam Fritzler\n"; 45 46#define ABYSS_IO_EXTENT 64 47 48static struct pci_device_id abyss_pci_tbl[] = { 49 { PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_MK2, 50 PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_TOKEN_RING << 8, 0x00ffffff, }, 51 { } /* Terminating entry */ 52}; 53MODULE_DEVICE_TABLE(pci, abyss_pci_tbl); 54 55MODULE_LICENSE("GPL"); 56 57static int abyss_open(struct net_device *dev); 58static int abyss_close(struct net_device *dev); 59static void abyss_enable(struct net_device *dev); 60static int abyss_chipset_init(struct net_device *dev); 61static void abyss_read_eeprom(struct net_device *dev); 62static unsigned short abyss_setnselout_pins(struct net_device *dev); 63 64static void at24_writedatabyte(unsigned long regaddr, unsigned char byte); 65static int at24_sendfullcmd(unsigned long regaddr, unsigned char cmd, unsigned char addr); 66static int at24_sendcmd(unsigned long regaddr, unsigned char cmd); 67static unsigned char at24_readdatabit(unsigned long regaddr); 68static unsigned char at24_readdatabyte(unsigned long regaddr); 69static int at24_waitforack(unsigned long regaddr); 70static int at24_waitfornack(unsigned long regaddr); 71static void at24_setlines(unsigned long regaddr, unsigned char clock, unsigned char data); 72static void at24_start(unsigned long regaddr); 73static unsigned char at24_readb(unsigned long regaddr, unsigned char addr); 74 75static unsigned short abyss_sifreadb(struct net_device *dev, unsigned short reg) 76{ 77 return inb(dev->base_addr + reg); 78} 79 80static unsigned short abyss_sifreadw(struct net_device *dev, unsigned short reg) 81{ 82 return inw(dev->base_addr + reg); 83} 84 85static void abyss_sifwriteb(struct net_device *dev, unsigned short val, unsigned short reg) 86{ 87 outb(val, dev->base_addr + reg); 88} 89 90static void abyss_sifwritew(struct net_device *dev, unsigned short val, unsigned short reg) 91{ 92 outw(val, dev->base_addr + reg); 93} 94 95static int __devinit abyss_attach(struct pci_dev *pdev, const struct pci_device_id *ent) 96{ 97 static int versionprinted; 98 struct net_device *dev; 99 struct net_local *tp; 100 int ret, pci_irq_line; 101 unsigned long pci_ioaddr; 102 DECLARE_MAC_BUF(mac); 103 104 if (versionprinted++ == 0) 105 printk("%s", version); 106 107 if (pci_enable_device(pdev)) 108 return -EIO; 109 110 /* Remove I/O space marker in bit 0. */ 111 pci_irq_line = pdev->irq; 112 pci_ioaddr = pci_resource_start (pdev, 0); 113 114 /* At this point we have found a valid card. */ 115 116 dev = alloc_trdev(sizeof(struct net_local)); 117 if (!dev) 118 return -ENOMEM; 119 120 if (!request_region(pci_ioaddr, ABYSS_IO_EXTENT, dev->name)) { 121 ret = -EBUSY; 122 goto err_out_trdev; 123 } 124 125 ret = request_irq(pdev->irq, tms380tr_interrupt, IRQF_SHARED, 126 dev->name, dev); 127 if (ret) 128 goto err_out_region; 129 130 dev->base_addr = pci_ioaddr; 131 dev->irq = pci_irq_line; 132 133 printk("%s: Madge Smart 16/4 PCI Mk2 (Abyss)\n", dev->name); 134 printk("%s: IO: %#4lx IRQ: %d\n", 135 dev->name, pci_ioaddr, dev->irq); 136 /* 137 * The TMS SIF registers lay 0x10 above the card base address. 138 */ 139 dev->base_addr += 0x10; 140 141 ret = tmsdev_init(dev, &pdev->dev); 142 if (ret) { 143 printk("%s: unable to get memory for dev->priv.\n", 144 dev->name); 145 goto err_out_irq; 146 } 147 148 abyss_read_eeprom(dev); 149 150 printk("%s: Ring Station Address: %s\n", 151 dev->name, print_mac(mac, dev->dev_addr)); 152 153 tp = netdev_priv(dev); 154 tp->setnselout = abyss_setnselout_pins; 155 tp->sifreadb = abyss_sifreadb; 156 tp->sifreadw = abyss_sifreadw; 157 tp->sifwriteb = abyss_sifwriteb; 158 tp->sifwritew = abyss_sifwritew; 159 160 memcpy(tp->ProductID, "Madge PCI 16/4 Mk2", PROD_ID_SIZE + 1); 161 162 dev->open = abyss_open; 163 dev->stop = abyss_close; 164 165 pci_set_drvdata(pdev, dev); 166 SET_NETDEV_DEV(dev, &pdev->dev); 167 168 ret = register_netdev(dev); 169 if (ret) 170 goto err_out_tmsdev; 171 return 0; 172 173err_out_tmsdev: 174 pci_set_drvdata(pdev, NULL); 175 tmsdev_term(dev); 176err_out_irq: 177 free_irq(pdev->irq, dev); 178err_out_region: 179 release_region(pci_ioaddr, ABYSS_IO_EXTENT); 180err_out_trdev: 181 free_netdev(dev); 182 return ret; 183} 184 185static unsigned short abyss_setnselout_pins(struct net_device *dev) 186{ 187 unsigned short val = 0; 188 struct net_local *tp = netdev_priv(dev); 189 190 if(tp->DataRate == SPEED_4) 191 val |= 0x01; /* Set 4Mbps */ 192 else 193 val |= 0x00; /* Set 16Mbps */ 194 195 return val; 196} 197 198/* 199 * The following Madge boards should use this code: 200 * - Smart 16/4 PCI Mk2 (Abyss) 201 * - Smart 16/4 PCI Mk1 (PCI T) 202 * - Smart 16/4 Client Plus PnP (Big Apple) 203 * - Smart 16/4 Cardbus Mk2 204 * 205 * These access an Atmel AT24 SEEPROM using their glue chip registers. 206 * 207 */ 208static void at24_writedatabyte(unsigned long regaddr, unsigned char byte) 209{ 210 int i; 211 212 for (i = 0; i < 8; i++) { 213 at24_setlines(regaddr, 0, (byte >> (7-i))&0x01); 214 at24_setlines(regaddr, 1, (byte >> (7-i))&0x01); 215 at24_setlines(regaddr, 0, (byte >> (7-i))&0x01); 216 } 217} 218 219static int at24_sendfullcmd(unsigned long regaddr, unsigned char cmd, unsigned char addr) 220{ 221 if (at24_sendcmd(regaddr, cmd)) { 222 at24_writedatabyte(regaddr, addr); 223 return at24_waitforack(regaddr); 224 } 225 return 0; 226} 227 228static int at24_sendcmd(unsigned long regaddr, unsigned char cmd) 229{ 230 int i; 231 232 for (i = 0; i < 10; i++) { 233 at24_start(regaddr); 234 at24_writedatabyte(regaddr, cmd); 235 if (at24_waitforack(regaddr)) 236 return 1; 237 } 238 return 0; 239} 240 241static unsigned char at24_readdatabit(unsigned long regaddr) 242{ 243 unsigned char val; 244 245 at24_setlines(regaddr, 0, 1); 246 at24_setlines(regaddr, 1, 1); 247 val = (inb(regaddr) & AT24_DATA)?1:0; 248 at24_setlines(regaddr, 1, 1); 249 at24_setlines(regaddr, 0, 1); 250 return val; 251} 252 253static unsigned char at24_readdatabyte(unsigned long regaddr) 254{ 255 unsigned char data = 0; 256 int i; 257 258 for (i = 0; i < 8; i++) { 259 data <<= 1; 260 data |= at24_readdatabit(regaddr); 261 } 262 263 return data; 264} 265 266static int at24_waitforack(unsigned long regaddr) 267{ 268 int i; 269 270 for (i = 0; i < 10; i++) { 271 if ((at24_readdatabit(regaddr) & 0x01) == 0x00) 272 return 1; 273 } 274 return 0; 275} 276 277static int at24_waitfornack(unsigned long regaddr) 278{ 279 int i; 280 for (i = 0; i < 10; i++) { 281 if ((at24_readdatabit(regaddr) & 0x01) == 0x01) 282 return 1; 283 } 284 return 0; 285} 286 287static void at24_setlines(unsigned long regaddr, unsigned char clock, unsigned char data) 288{ 289 unsigned char val = AT24_ENABLE; 290 if (clock) 291 val |= AT24_CLOCK; 292 if (data) 293 val |= AT24_DATA; 294 295 outb(val, regaddr); 296 tms380tr_wait(20); /* Very necessary. */ 297} 298 299static void at24_start(unsigned long regaddr) 300{ 301 at24_setlines(regaddr, 0, 1); 302 at24_setlines(regaddr, 1, 1); 303 at24_setlines(regaddr, 1, 0); 304 at24_setlines(regaddr, 0, 1); 305} 306 307static unsigned char at24_readb(unsigned long regaddr, unsigned char addr) 308{ 309 unsigned char data = 0xff; 310 311 if (at24_sendfullcmd(regaddr, AT24_WRITE, addr)) { 312 if (at24_sendcmd(regaddr, AT24_READ)) { 313 data = at24_readdatabyte(regaddr); 314 if (!at24_waitfornack(regaddr)) 315 data = 0xff; 316 } 317 } 318 return data; 319} 320 321 322/* 323 * Enable basic functions of the Madge chipset needed 324 * for initialization. 325 */ 326static void abyss_enable(struct net_device *dev) 327{ 328 unsigned char reset_reg; 329 unsigned long ioaddr; 330 331 ioaddr = dev->base_addr; 332 reset_reg = inb(ioaddr + PCIBM2_RESET_REG); 333 reset_reg |= PCIBM2_RESET_REG_CHIP_NRES; 334 outb(reset_reg, ioaddr + PCIBM2_RESET_REG); 335 tms380tr_wait(100); 336} 337 338/* 339 * Enable the functions of the Madge chipset needed for 340 * full working order. 341 */ 342static int abyss_chipset_init(struct net_device *dev) 343{ 344 unsigned char reset_reg; 345 unsigned long ioaddr; 346 347 ioaddr = dev->base_addr; 348 349 reset_reg = inb(ioaddr + PCIBM2_RESET_REG); 350 351 reset_reg |= PCIBM2_RESET_REG_CHIP_NRES; 352 outb(reset_reg, ioaddr + PCIBM2_RESET_REG); 353 354 reset_reg &= ~(PCIBM2_RESET_REG_CHIP_NRES | 355 PCIBM2_RESET_REG_FIFO_NRES | 356 PCIBM2_RESET_REG_SIF_NRES); 357 outb(reset_reg, ioaddr + PCIBM2_RESET_REG); 358 359 tms380tr_wait(100); 360 361 reset_reg |= PCIBM2_RESET_REG_CHIP_NRES; 362 outb(reset_reg, ioaddr + PCIBM2_RESET_REG); 363 364 reset_reg |= PCIBM2_RESET_REG_SIF_NRES; 365 outb(reset_reg, ioaddr + PCIBM2_RESET_REG); 366 367 reset_reg |= PCIBM2_RESET_REG_FIFO_NRES; 368 outb(reset_reg, ioaddr + PCIBM2_RESET_REG); 369 370 outb(PCIBM2_INT_CONTROL_REG_SINTEN | 371 PCIBM2_INT_CONTROL_REG_PCI_ERR_ENABLE, 372 ioaddr + PCIBM2_INT_CONTROL_REG); 373 374 outb(30, ioaddr + PCIBM2_FIFO_THRESHOLD); 375 376 return 0; 377} 378 379static inline void abyss_chipset_close(struct net_device *dev) 380{ 381 unsigned long ioaddr; 382 383 ioaddr = dev->base_addr; 384 outb(0, ioaddr + PCIBM2_RESET_REG); 385} 386 387/* 388 * Read configuration data from the AT24 SEEPROM on Madge cards. 389 * 390 */ 391static void abyss_read_eeprom(struct net_device *dev) 392{ 393 struct net_local *tp; 394 unsigned long ioaddr; 395 unsigned short val; 396 int i; 397 398 tp = netdev_priv(dev); 399 ioaddr = dev->base_addr; 400 401 /* Must enable glue chip first */ 402 abyss_enable(dev); 403 404 val = at24_readb(ioaddr + PCIBM2_SEEPROM_REG, 405 PCIBM2_SEEPROM_RING_SPEED); 406 tp->DataRate = val?SPEED_4:SPEED_16; /* set open speed */ 407 printk("%s: SEEPROM: ring speed: %dMb/sec\n", dev->name, tp->DataRate); 408 409 val = at24_readb(ioaddr + PCIBM2_SEEPROM_REG, 410 PCIBM2_SEEPROM_RAM_SIZE) * 128; 411 printk("%s: SEEPROM: adapter RAM: %dkb\n", dev->name, val); 412 413 dev->addr_len = 6; 414 for (i = 0; i < 6; i++) 415 dev->dev_addr[i] = at24_readb(ioaddr + PCIBM2_SEEPROM_REG, 416 PCIBM2_SEEPROM_BIA+i); 417} 418 419static int abyss_open(struct net_device *dev) 420{ 421 abyss_chipset_init(dev); 422 tms380tr_open(dev); 423 return 0; 424} 425 426static int abyss_close(struct net_device *dev) 427{ 428 tms380tr_close(dev); 429 abyss_chipset_close(dev); 430 return 0; 431} 432 433static void __devexit abyss_detach (struct pci_dev *pdev) 434{ 435 struct net_device *dev = pci_get_drvdata(pdev); 436 437 BUG_ON(!dev); 438 unregister_netdev(dev); 439 release_region(dev->base_addr-0x10, ABYSS_IO_EXTENT); 440 free_irq(dev->irq, dev); 441 tmsdev_term(dev); 442 free_netdev(dev); 443 pci_set_drvdata(pdev, NULL); 444} 445 446static struct pci_driver abyss_driver = { 447 .name = "abyss", 448 .id_table = abyss_pci_tbl, 449 .probe = abyss_attach, 450 .remove = __devexit_p(abyss_detach), 451}; 452 453static int __init abyss_init (void) 454{ 455 return pci_register_driver(&abyss_driver); 456} 457 458static void __exit abyss_rmmod (void) 459{ 460 pci_unregister_driver (&abyss_driver); 461} 462 463module_init(abyss_init); 464module_exit(abyss_rmmod); 465