tmsisa.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:11k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  tmsisa.c: A generic network driver for TMS380-based ISA token ring cards.
  3.  *
  4.  *  Based on tmspci written 1999 by Adam Fritzler
  5.  *  
  6.  *  Written 2000 by Jochen Friedrich
  7.  *  Dedicated to my girlfriend Steffi Bopp
  8.  *
  9.  *  This software may be used and distributed according to the terms
  10.  *  of the GNU General Public License, incorporated herein by reference.
  11.  *
  12.  *  This driver module supports the following cards:
  13.  * - SysKonnect TR4/16(+) ISA (SK-4190)
  14.  *
  15.  *  Maintainer(s):
  16.  *    AF        Adam Fritzler           mid@auk.cx
  17.  *    JF Jochen Friedrich jochen@scram.de
  18.  *
  19.  *  TODO:
  20.  * 1. Add support for Proteon TR ISA adapters (1392, 1392+)
  21.  */
  22. static const char version[] = "tmsisa.c: v1.00 14/01/2001 by Jochen Friedrichn";
  23. #include <linux/module.h>
  24. #include <linux/kernel.h>
  25. #include <linux/sched.h>
  26. #include <linux/errno.h>
  27. #include <linux/pci.h>
  28. #include <linux/init.h>
  29. #include <asm/system.h>
  30. #include <asm/io.h>
  31. #include <asm/irq.h>
  32. #include <asm/pci.h>
  33. #include <asm/dma.h>
  34. #include <linux/netdevice.h>
  35. #include <linux/trdevice.h>
  36. #include "tms380tr.h"
  37. #define TMS_ISA_IO_EXTENT 32
  38. /* A zero-terminated list of I/O addresses to be probed. */
  39. static unsigned int portlist[] __initdata = {
  40. 0x0A20, 0x1A20, 0x0B20, 0x1B20, 0x0980, 0x1980, 0x0900, 0x1900,// SK
  41. 0
  42. };
  43. /* A zero-terminated list of IRQs to be probed. 
  44.  * Used again after initial probe for sktr_chipset_init, called from sktr_open.
  45.  */
  46. static unsigned short irqlist[] = {
  47. 3, 5, 9, 10, 11, 12, 15,
  48. 0
  49. };
  50. /* A zero-terminated list of DMAs to be probed. */
  51. static int dmalist[] __initdata = {
  52. 5, 6, 7,
  53. 0
  54. };
  55. static char isa_cardname[] = "SK NET TR 4/16 ISA";
  56. int tms_isa_probe(struct net_device *dev);
  57. static int tms_isa_open(struct net_device *dev);
  58. static int tms_isa_close(struct net_device *dev);
  59. static void tms_isa_read_eeprom(struct net_device *dev);
  60. static unsigned short tms_isa_setnselout_pins(struct net_device *dev);
  61. static unsigned short tms_isa_sifreadb(struct net_device *dev, unsigned short reg)
  62. {
  63. return inb(dev->base_addr + reg);
  64. }
  65. static unsigned short tms_isa_sifreadw(struct net_device *dev, unsigned short reg)
  66. {
  67. return inw(dev->base_addr + reg);
  68. }
  69. static void tms_isa_sifwriteb(struct net_device *dev, unsigned short val, unsigned short reg)
  70. {
  71. outb(val, dev->base_addr + reg);
  72. }
  73. static void tms_isa_sifwritew(struct net_device *dev, unsigned short val, unsigned short reg)
  74. {
  75. outw(val, dev->base_addr + reg);
  76. }
  77. struct tms_isa_card {
  78. struct net_device *dev;
  79. struct tms_isa_card *next;
  80. };
  81. static struct tms_isa_card *tms_isa_card_list;
  82. static int __init tms_isa_probe1(int ioaddr)
  83. {
  84. unsigned char old, chk1, chk2;
  85. old = inb(ioaddr + SIFADR); /* Get the old SIFADR value */
  86. chk1 = 0; /* Begin with check value 0 */
  87. do {
  88. /* Write new SIFADR value */
  89. outb(chk1, ioaddr + SIFADR);
  90. /* Read, invert and write */
  91. chk2 = inb(ioaddr + SIFADD);
  92. chk2 ^= 0x0FE;
  93. outb(chk2, ioaddr + SIFADR);
  94. /* Read, invert and compare */
  95. chk2 = inb(ioaddr + SIFADD);
  96. chk2 ^= 0x0FE;
  97. if(chk1 != chk2)
  98. return (-1); /* No adapter */
  99. chk1 -= 2;
  100. } while(chk1 != 0); /* Repeat 128 times (all byte values) */
  101.      /* Restore the SIFADR value */
  102. outb(old, ioaddr + SIFADR);
  103. return (0);
  104. }
  105. int __init tms_isa_probe(struct net_device *dev)
  106. {
  107.         static int versionprinted;
  108. struct net_local *tp;
  109. int j;
  110. struct tms_isa_card *card;
  111. if(check_region(dev->base_addr, TMS_ISA_IO_EXTENT))
  112. return -1;
  113. if(tms_isa_probe1(dev->base_addr))
  114. return -1;
  115.    
  116. if (versionprinted++ == 0)
  117. printk("%s", version);
  118.  
  119. /* At this point we have found a valid card. */
  120.     
  121. if (!request_region(dev->base_addr, TMS_ISA_IO_EXTENT, isa_cardname))
  122. return -1;
  123. if (tmsdev_init(dev, ISA_MAX_ADDRESS, NULL))
  124.         {
  125. release_region(dev->base_addr, TMS_ISA_IO_EXTENT); 
  126. return -1;
  127. }
  128. dev->base_addr &= ~3; 
  129. tms_isa_read_eeprom(dev);
  130. printk("%s:    Ring Station Address: ", dev->name);
  131. printk("%2.2x", dev->dev_addr[0]);
  132. for (j = 1; j < 6; j++)
  133. printk(":%2.2x", dev->dev_addr[j]);
  134. printk("n");
  135. tp = (struct net_local *)dev->priv;
  136. tp->setnselout = tms_isa_setnselout_pins;
  137. tp->sifreadb = tms_isa_sifreadb;
  138. tp->sifreadw = tms_isa_sifreadw;
  139. tp->sifwriteb = tms_isa_sifwriteb;
  140. tp->sifwritew = tms_isa_sifwritew;
  141. memcpy(tp->ProductID, isa_cardname, PROD_ID_SIZE + 1);
  142. tp->tmspriv = NULL;
  143. dev->open = tms_isa_open;
  144. dev->stop = tms_isa_close;
  145. if (dev->irq == 0)
  146. {
  147. for(j = 0; irqlist[j] != 0; j++)
  148. {
  149. dev->irq = irqlist[j];
  150. if (!request_irq(dev->irq, tms380tr_interrupt, 0, 
  151. isa_cardname, dev))
  152. break;
  153.                 }
  154.                 if(irqlist[j] == 0)
  155.                 {
  156.                         printk("%s: AutoSelect no IRQ availablen", dev->name);
  157. release_region(dev->base_addr, TMS_ISA_IO_EXTENT); 
  158. tmsdev_term(dev);
  159. return -1;
  160. }
  161. }
  162. else
  163. {
  164. for(j = 0; irqlist[j] != 0; j++)
  165. if (irqlist[j] == dev->irq)
  166. break;
  167. if (irqlist[j] == 0)
  168. {
  169. printk("%s: Illegal IRQ %d specifiedn",
  170. dev->name, dev->irq);
  171. release_region(dev->base_addr, TMS_ISA_IO_EXTENT); 
  172. tmsdev_term(dev);
  173. return -1;
  174. }
  175. if (request_irq(dev->irq, tms380tr_interrupt, 0, 
  176. isa_cardname, dev))
  177. {
  178.                         printk("%s: Selected IRQ %d not availablen", 
  179. dev->name, dev->irq);
  180. release_region(dev->base_addr, TMS_ISA_IO_EXTENT); 
  181. tmsdev_term(dev);
  182. return -1;
  183. }
  184. }
  185. if (dev->dma == 0)
  186. {
  187. for(j = 0; dmalist[j] != 0; j++)
  188. {
  189. dev->dma = dmalist[j];
  190.                         if (!request_dma(dev->dma, isa_cardname))
  191. break;
  192. }
  193. if(dmalist[j] == 0)
  194. {
  195. printk("%s: AutoSelect no DMA availablen", dev->name);
  196. release_region(dev->base_addr, TMS_ISA_IO_EXTENT); 
  197. free_irq(dev->irq, dev);
  198. tmsdev_term(dev);
  199. return -1;
  200. }
  201. }
  202. else
  203. {
  204. for(j = 0; dmalist[j] != 0; j++)
  205. if (dmalist[j] == dev->dma)
  206. break;
  207. if (dmalist[j] == 0)
  208. {
  209.                         printk("%s: Illegal DMA %d specifiedn", 
  210. dev->name, dev->dma);
  211. release_region(dev->base_addr, TMS_ISA_IO_EXTENT); 
  212. free_irq(dev->irq, dev);
  213. tmsdev_term(dev);
  214. return -1;
  215. }
  216. if (request_dma(dev->dma, isa_cardname))
  217. {
  218.                         printk("%s: Selected DMA %d not availablen", 
  219. dev->name, dev->dma);
  220. release_region(dev->base_addr, TMS_ISA_IO_EXTENT); 
  221. free_irq(dev->irq, dev);
  222. tmsdev_term(dev);
  223. return -1;
  224. }
  225. }
  226. printk("%s:    IO: %#4lx  IRQ: %d  DMA: %dn",
  227.        dev->name, dev->base_addr, dev->irq, dev->dma);
  228. if (register_trdev(dev) == 0) 
  229. {
  230. /* Enlist in the card list */
  231. card = kmalloc(sizeof(struct tms_isa_card), GFP_KERNEL);
  232. if (!card) {
  233. unregister_trdev(dev);
  234. release_region(dev->base_addr, TMS_ISA_IO_EXTENT); 
  235. free_irq(dev->irq, dev);
  236. free_dma(dev->dma);
  237. tmsdev_term(dev);
  238. return -1;
  239. }
  240. card->next = tms_isa_card_list;
  241. tms_isa_card_list = card;
  242. card->dev = dev;
  243. else 
  244. {
  245. printk("%s: register_trdev() returned non-zero.n", dev->name);
  246. release_region(dev->base_addr, TMS_ISA_IO_EXTENT); 
  247. free_irq(dev->irq, dev);
  248. free_dma(dev->dma);
  249. tmsdev_term(dev);
  250. return -1;
  251. }
  252. return 0;
  253. }
  254. /*
  255.  * Reads MAC address from adapter RAM, which should've read it from
  256.  * the onboard ROM.  
  257.  *
  258.  * Calling this on a board that does not support it can be a very
  259.  * dangerous thing.  The Madge board, for instance, will lock your
  260.  * machine hard when this is called.  Luckily, its supported in a
  261.  * seperate driver.  --ASF
  262.  */
  263. static void tms_isa_read_eeprom(struct net_device *dev)
  264. {
  265. int i;
  266. /* Address: 0000:0000 */
  267. tms_isa_sifwritew(dev, 0, SIFADX);
  268. tms_isa_sifwritew(dev, 0, SIFADR);
  269. /* Read six byte MAC address data */
  270. dev->addr_len = 6;
  271. for(i = 0; i < 6; i++)
  272. dev->dev_addr[i] = tms_isa_sifreadw(dev, SIFINC) >> 8;
  273. }
  274. unsigned short tms_isa_setnselout_pins(struct net_device *dev)
  275. {
  276. return 0;
  277. }
  278. static int tms_isa_open(struct net_device *dev)
  279. {  
  280. struct net_local *tp = (struct net_local *)dev->priv;
  281. unsigned short val = 0;
  282. unsigned short oldval;
  283. int i;
  284. val = 0;
  285. for(i = 0; irqlist[i] != 0; i++)
  286. {
  287. if(irqlist[i] == dev->irq)
  288. break;
  289. }
  290. val |= CYCLE_TIME << 2;
  291. val |= i << 4;
  292. i = dev->dma - 5;
  293. val |= i;
  294. if(tp->DataRate == SPEED_4)
  295. val |= LINE_SPEED_BIT;
  296. else
  297. val &= ~LINE_SPEED_BIT;
  298. oldval = tms_isa_sifreadb(dev, POSREG);
  299. /* Leave cycle bits alone */
  300. oldval |= 0xf3;
  301. val &= oldval;
  302. tms_isa_sifwriteb(dev, val, POSREG);
  303. tms380tr_open(dev);
  304. MOD_INC_USE_COUNT;
  305. return 0;
  306. }
  307. static int tms_isa_close(struct net_device *dev)
  308. {
  309. tms380tr_close(dev);
  310. MOD_DEC_USE_COUNT;
  311. return 0;
  312. }
  313. #ifdef MODULE
  314. #define ISATR_MAX_ADAPTERS 3
  315. static int io[ISATR_MAX_ADAPTERS];
  316. static int irq[ISATR_MAX_ADAPTERS];
  317. static int dma[ISATR_MAX_ADAPTERS];
  318. MODULE_LICENSE("GPL");
  319. MODULE_PARM(io, "1-" __MODULE_STRING(ISATR_MAX_ADAPTERS) "i");
  320. MODULE_PARM(irq, "1-" __MODULE_STRING(ISATR_MAX_ADAPTERS) "i");
  321. MODULE_PARM(dma, "1-" __MODULE_STRING(ISATR_MAX_ADAPTERS) "i");
  322. int init_module(void)
  323. {
  324. int i, num;
  325. struct net_device *dev;
  326. num = 0;
  327. if (io[0]) 
  328. { /* Only probe addresses from command line */
  329. for (i = 0; i < ISATR_MAX_ADAPTERS; i++)
  330.         {
  331. if (io[i] == 0)
  332. continue;
  333. dev = init_trdev(NULL, 0);
  334. if (!dev)
  335. return (-ENOMEM);
  336. dev->base_addr = io[i];
  337. dev->irq       = irq[i];
  338. dev->dma       = dma[i];
  339. if (tms_isa_probe(dev))
  340. {
  341. unregister_netdev(dev);
  342. kfree(dev);
  343. }
  344. else
  345. num++;
  346. }
  347. }
  348.         else
  349.         {
  350. for(i = 0; portlist[i]; i++)
  351. {
  352. if (num >= ISATR_MAX_ADAPTERS)
  353. continue;
  354. dev = init_trdev(NULL, 0);
  355. if (!dev)
  356. return (-ENOMEM);
  357. dev->base_addr = portlist[i];
  358. dev->irq       = irq[num];
  359. dev->dma       = dma[num];
  360. if (tms_isa_probe(dev))
  361. {
  362. unregister_netdev(dev);
  363. kfree(dev);
  364. }
  365. else
  366. num++;
  367. }
  368. }
  369. printk(KERN_NOTICE "tmsisa.c: %d cards found.n", num);
  370. /* Probe for cards. */
  371. if (num == 0) {
  372. printk(KERN_NOTICE "tmsisa.c: No cards found.n");
  373. }
  374. return (0);
  375. }
  376. void cleanup_module(void)
  377. {
  378. struct net_device *dev;
  379. struct tms_isa_card *this_card;
  380. while (tms_isa_card_list) {
  381. dev = tms_isa_card_list->dev;
  382. unregister_netdev(dev);
  383. release_region(dev->base_addr, TMS_ISA_IO_EXTENT);
  384. free_irq(dev->irq, dev);
  385. free_dma(dev->dma);
  386. tmsdev_term(dev);
  387. kfree(dev);
  388. this_card = tms_isa_card_list;
  389. tms_isa_card_list = this_card->next;
  390. kfree(this_card);
  391. }
  392. }
  393. #endif /* MODULE */
  394. /*
  395.  * Local variables:
  396.  *  compile-command: "gcc -DMODVERSIONS  -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tmsisa.c"
  397.  *  alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tmsisa.c"
  398.  *  c-set-style "K&R"
  399.  *  c-indent-level: 8
  400.  *  c-basic-offset: 8
  401.  *  tab-width: 8
  402.  * End:
  403.  */