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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: eicon_isa.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
  2.  *
  3.  * ISDN low-level module for Eicon active ISDN-Cards.
  4.  * Hardware-specific code for old ISA cards.
  5.  *
  6.  * Copyright 1998      by Fritz Elfert (fritz@isdn4linux.de)
  7.  * Copyright 1998-2000 by Armin Schindler (mac@melware.de)
  8.  * Copyright 1999,2000 Cytronics & Melware (info@melware.de)
  9.  *
  10.  * This software may be used and distributed according to the terms
  11.  * of the GNU General Public License, incorporated herein by reference.
  12.  *
  13.  */
  14. #include <linux/config.h>
  15. #include "eicon.h"
  16. #include "eicon_isa.h"
  17. #define check_shmem   check_region
  18. #define release_shmem release_region
  19. #define request_shmem request_region
  20. char *eicon_isa_revision = "$Revision: 1.1.4.1 $";
  21. #undef EICON_MCA_DEBUG
  22. #ifdef CONFIG_ISDN_DRV_EICON_ISA
  23. /* Mask for detecting invalid IRQ parameter */
  24. static int eicon_isa_valid_irq[] = {
  25. 0x1c1c, /* 2, 3, 4, 10, 11, 12 (S)*/
  26. 0x1c1c, /* 2, 3, 4, 10, 11, 12 (SX) */
  27. 0x1cbc, /* 2, 3, 4, 5, 7, 10, 11, 12 (SCOM) */
  28. 0x1cbc, /* 2, 3, 4, 5, 6, 10, 11, 12 (Quadro) */
  29. 0x1cbc  /* 2, 3, 4, 5, 7, 10, 11, 12 (S2M) */
  30. };
  31. static void
  32. eicon_isa_release_shmem(eicon_isa_card *card) {
  33. if (card->mvalid) {
  34. iounmap(card->shmem);
  35. release_mem_region(card->physmem, card->ramsize);
  36. }
  37. card->mvalid = 0;
  38. }
  39. static void
  40. eicon_isa_release_irq(eicon_isa_card *card) {
  41. if (!card->master)
  42. return;
  43. if (card->ivalid)
  44. free_irq(card->irq, card);
  45. card->ivalid = 0;
  46. }
  47. void
  48. eicon_isa_release(eicon_isa_card *card) {
  49. eicon_isa_release_irq(card);
  50. eicon_isa_release_shmem(card);
  51. }
  52. void
  53. eicon_isa_printpar(eicon_isa_card *card) {
  54. switch (card->type) {
  55. case EICON_CTYPE_S:
  56. case EICON_CTYPE_SX:
  57. case EICON_CTYPE_SCOM:
  58. case EICON_CTYPE_QUADRO:
  59. case EICON_CTYPE_S2M:
  60. printk(KERN_INFO "Eicon %s at 0x%lx, irq %d.n",
  61.        eicon_ctype_name[card->type],
  62.        card->physmem,
  63.        card->irq);
  64. }
  65. }
  66. int
  67. eicon_isa_find_card(int Mem, int Irq, char * Id)
  68. {
  69. int primary = 1;
  70. unsigned long amem;
  71. if (!strlen(Id))
  72. return -1;
  73. if (Mem == -1)
  74. return -1;
  75. /* Check for valid membase address */
  76. if ((Mem < 0x0c0000) ||
  77.     (Mem > 0x0fc000) ||
  78.     (Mem & 0xfff)) { 
  79. printk(KERN_WARNING "eicon_isa: illegal membase 0x%x for %sn",
  80.  Mem, Id);
  81. return -1;
  82. }
  83. if (check_mem_region(Mem, RAMSIZE)) {
  84. printk(KERN_WARNING "eicon_isa_boot: memory at 0x%x already in use.n", Mem);
  85. return -1;
  86. }
  87. amem = (unsigned long) ioremap(Mem, RAMSIZE);
  88.         writew(0x55aa, amem + 0x402);
  89.         if (readw(amem + 0x402) != 0x55aa) primary = 0;
  90. writew(0, amem + 0x402);
  91. if (readw(amem + 0x402) != 0) primary = 0;
  92. printk(KERN_INFO "Eicon: Driver-ID: %sn", Id);
  93. if (primary) {
  94. printk(KERN_INFO "Eicon: assuming pri card at 0x%xn", Mem);
  95. writeb(0, amem + 0x3ffe);
  96. iounmap((unsigned char *)amem);
  97. return EICON_CTYPE_ISAPRI;
  98. } else {
  99. printk(KERN_INFO "Eicon: assuming bri card at 0x%xn", Mem);
  100. writeb(0, amem + 0x400);
  101. iounmap((unsigned char *)amem);
  102. return EICON_CTYPE_ISABRI;
  103. }
  104. return -1;
  105. }
  106. int
  107. eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) {
  108. int tmp;
  109. int               timeout;
  110. eicon_isa_codebuf cbuf;
  111. unsigned char     *code;
  112. eicon_isa_boot    *boot;
  113. if (copy_from_user(&cbuf, cb, sizeof(eicon_isa_codebuf)))
  114. return -EFAULT;
  115. /* Allocate code-buffer and copy code from userspace */
  116. if (cbuf.bootstrap_len > 1024) {
  117. printk(KERN_WARNING "eicon_isa_boot: Invalid startup-code size %ldn",
  118.        cbuf.bootstrap_len);
  119. return -EINVAL;
  120. }
  121. if (!(code = kmalloc(cbuf.bootstrap_len, GFP_KERNEL))) {
  122. printk(KERN_WARNING "eicon_isa_boot: Couldn't allocate code buffern");
  123. return -ENOMEM;
  124. }
  125. if (copy_from_user(code, &cb->code, cbuf.bootstrap_len)) {
  126. kfree(code);
  127. return -EFAULT;
  128. }
  129. if (card->type == EICON_CTYPE_ISAPRI)
  130. card->ramsize  = RAMSIZE_P;
  131. else
  132. card->ramsize  = RAMSIZE;
  133. if (check_mem_region(card->physmem, card->ramsize)) {
  134. printk(KERN_WARNING "eicon_isa_boot: memory at 0x%lx already in use.n",
  135. card->physmem);
  136. kfree(code);
  137. return -EBUSY;
  138. }
  139. request_mem_region(card->physmem, card->ramsize, "Eicon ISA ISDN");
  140. card->shmem = (eicon_isa_shmem *) ioremap(card->physmem, card->ramsize);
  141. #ifdef EICON_MCA_DEBUG
  142. printk(KERN_INFO "eicon_isa_boot: card->ramsize = %d.n", card->ramsize);
  143. #endif
  144. card->mvalid = 1;
  145. switch(card->type) {
  146. case EICON_CTYPE_S:
  147. case EICON_CTYPE_SX:
  148. case EICON_CTYPE_SCOM:
  149. case EICON_CTYPE_QUADRO:
  150. case EICON_CTYPE_ISABRI:
  151. card->intack   = (__u8 *)card->shmem + INTACK;
  152. card->startcpu = (__u8 *)card->shmem + STARTCPU;
  153. card->stopcpu  = (__u8 *)card->shmem + STOPCPU;
  154. break;
  155. case EICON_CTYPE_S2M:
  156. case EICON_CTYPE_ISAPRI:
  157. card->intack   = (__u8 *)card->shmem + INTACK_P;
  158. card->startcpu = (__u8 *)card->shmem + STARTCPU_P;
  159. card->stopcpu  = (__u8 *)card->shmem + STOPCPU_P;
  160. break;
  161. default:
  162. printk(KERN_WARNING "eicon_isa_boot: Invalid card type %dn", card->type);
  163. eicon_isa_release_shmem(card);
  164. kfree(code);
  165. return -EINVAL;
  166. }
  167. /* clear any pending irq's */
  168. readb(card->intack);
  169. #ifdef CONFIG_MCA
  170. if (MCA_bus) {
  171. if (card->type == EICON_CTYPE_SCOM) {
  172. outb_p(0,card->io+1);
  173. }
  174. else {
  175. printk(KERN_WARNING "eicon_isa_boot: Card type not supported yet.n");
  176. eicon_isa_release_shmem(card);
  177. return -EINVAL;
  178. };
  179. #ifdef EICON_MCA_DEBUG
  180. printk(KERN_INFO "eicon_isa_boot: card->io      = %x.n", card->io);
  181. printk(KERN_INFO "eicon_isa_boot: card->irq     = %d.n", (int)card->irq);
  182. #endif
  183. }
  184. #else
  185. /* set reset-line active */
  186. writeb(0, card->stopcpu); 
  187. #endif  /* CONFIG_MCA */
  188. /* clear irq-requests */
  189. writeb(0, card->intack);
  190. readb(card->intack);
  191. /* Copy code into card */
  192. memcpy_toio(&card->shmem->c, code, cbuf.bootstrap_len);
  193. /* Check for properly loaded code */
  194. if (!check_signature((unsigned long)&card->shmem->c, code, 1020)) {
  195. printk(KERN_WARNING "eicon_isa_boot: Could not load startup-coden");
  196. eicon_isa_release_shmem(card);
  197. kfree(code);
  198. return -EIO;
  199. }
  200. /* if 16k-ramsize, duplicate the reset-jump-code */
  201. if (card->ramsize == RAMSIZE_P)
  202. memcpy_toio((__u8 *)card->shmem + 0x3ff0, &code[0x3f0], 12);
  203. kfree(code);
  204. boot = &card->shmem->boot;
  205. /* Delay 0.2 sec. */
  206. SLEEP(HZ / 5);
  207. /* Start CPU */
  208. writeb(cbuf.boot_opt, &boot->ctrl);
  209. #ifdef CONFIG_MCA
  210. if (MCA_bus) {
  211. outb_p(0, card->io);
  212. }
  213. #else 
  214. writeb(0, card->startcpu); 
  215. #endif /* CONFIG_MCA */
  216. /* Delay 0.2 sec. */
  217. SLEEP(HZ / 5);
  218. timeout = jiffies + (HZ * 22);
  219. while (time_before(jiffies, timeout)) {
  220. if (readb(&boot->ctrl) == 0)
  221. break;
  222. SLEEP(10);
  223. }
  224. if (readb(&boot->ctrl) != 0) {
  225. printk(KERN_WARNING "eicon_isa_boot: CPU test failed.n");
  226. #ifdef EICON_MCA_DEBUG
  227. printk(KERN_INFO "eicon_isa_boot: &boot->ctrl = %d.n",
  228. readb(&boot->ctrl));
  229. #endif
  230. eicon_isa_release_shmem(card);
  231. return -EIO;
  232. }
  233. /* Check for memory-test errors */
  234. if (readw(&boot->ebit)) {
  235. printk(KERN_WARNING "eicon_isa_boot: memory test failed (bit 0x%04x at 0x%08x)n",
  236.        readw(&boot->ebit), readl(&boot->eloc));
  237. eicon_isa_release_shmem(card);
  238. return -EIO;
  239. }
  240.         /* Check card type and memory size */
  241.         tmp = readb(&boot->card);
  242. if ((tmp < 0) || (tmp > 4)) {
  243. printk(KERN_WARNING "eicon_isa_boot: Type detect failedn");
  244. eicon_isa_release_shmem(card);
  245. return -EIO;
  246. }
  247. card->type = tmp;
  248. ((eicon_card *)card->card)->type = tmp;
  249.         tmp = readb(&boot->msize);
  250.         if (tmp != 8 && tmp != 16 && tmp != 24 &&
  251.             tmp != 32 && tmp != 48 && tmp != 60) {
  252.                 printk(KERN_WARNING "eicon_isa_boot: invalid memsizen");
  253. eicon_isa_release_shmem(card);
  254.                 return -EIO;
  255.         }
  256. printk(KERN_INFO "%s: startup-code loadedn", eicon_ctype_name[card->type]); 
  257. if ((card->type == EICON_CTYPE_QUADRO) && (card->master)) {
  258. tmp = eicon_addcard(card->type, card->physmem, card->irq, 
  259. ((eicon_card *)card->card)->regname, 0);
  260. printk(KERN_INFO "Eicon: %d adapters addedn", tmp);
  261. }
  262. return 0;
  263. }
  264. int
  265. eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) {
  266. eicon_isa_boot    *boot;
  267. int               tmp;
  268. int               timeout;
  269. int    j;
  270. eicon_isa_codebuf cbuf;
  271. unsigned char     *code;
  272. unsigned char     *p;
  273. if (copy_from_user(&cbuf, cb, sizeof(eicon_isa_codebuf)))
  274. return -EFAULT;
  275. if (!(code = kmalloc(cbuf.firmware_len, GFP_KERNEL))) {
  276. printk(KERN_WARNING "eicon_isa_load: Couldn't allocate code buffern");
  277. return -ENOMEM;
  278. }
  279. if (copy_from_user(code, &cb->code, cbuf.firmware_len)) {
  280. kfree(code);
  281. return -EFAULT;
  282. }
  283. boot = &card->shmem->boot;
  284. if ((!card->ivalid) && card->master) {
  285. card->irqprobe = 1;
  286. /* Check for valid IRQ */
  287. if ((card->irq < 0) || (card->irq > 15) || 
  288.     (!((1 << card->irq) & eicon_isa_valid_irq[card->type & 0x0f]))) {
  289. printk(KERN_WARNING "eicon_isa_load: illegal irq: %dn", card->irq);
  290. eicon_isa_release_shmem(card);
  291. kfree(code);
  292. return -EINVAL;
  293. }
  294. /* Register irq */
  295. if (!request_irq(card->irq, &eicon_irq, 0, "Eicon ISA ISDN", card))
  296. card->ivalid = 1;
  297. else {
  298. printk(KERN_WARNING "eicon_isa_load: irq %d already in use.n",
  299.        card->irq);
  300. eicon_isa_release_shmem(card);
  301. kfree(code);
  302. return -EBUSY;
  303. }
  304. }
  305.         tmp = readb(&boot->msize);
  306.         if (tmp != 8 && tmp != 16 && tmp != 24 &&
  307.             tmp != 32 && tmp != 48 && tmp != 60) {
  308.                 printk(KERN_WARNING "eicon_isa_load: invalid memsizen");
  309. eicon_isa_release_shmem(card);
  310.                 return -EIO;
  311.         }
  312. eicon_isa_printpar(card);
  313. /* Download firmware */
  314. printk(KERN_INFO "%s %dkB, loading firmware ...n", 
  315.        eicon_ctype_name[card->type],
  316.        tmp * 16);
  317. tmp = cbuf.firmware_len >> 8;
  318. p = code;
  319. while (tmp--) {
  320. memcpy_toio(&boot->b, p, 256);
  321. writeb(1, &boot->ctrl);
  322. timeout = jiffies + HZ / 10;
  323. while (time_before(jiffies, timeout)) {
  324. if (readb(&boot->ctrl) == 0)
  325. break;
  326. SLEEP(2);
  327. }
  328. if (readb(&boot->ctrl)) {
  329. printk(KERN_WARNING "eicon_isa_load: download timeout at 0x%xn", p-code);
  330. eicon_isa_release(card);
  331. kfree(code);
  332. return -EIO;
  333. }
  334. p += 256;
  335. }
  336. kfree(code);
  337. /* Initialize firmware parameters */
  338. memcpy_toio(&card->shmem->c[8], &cbuf.tei, 14);
  339. memcpy_toio(&card->shmem->c[32], &cbuf.oad, 96);
  340. memcpy_toio(&card->shmem->c[128], &cbuf.oad, 96);
  341. /* Start firmware, wait for signature */
  342. writeb(2, &boot->ctrl);
  343. timeout = jiffies + (5*HZ);
  344. while (time_before(jiffies, timeout)) {
  345. if (readw(&boot->signature) == 0x4447)
  346. break;
  347. SLEEP(2);
  348. }
  349. if (readw(&boot->signature) != 0x4447) {
  350. printk(KERN_WARNING "eicon_isa_load: firmware selftest failed %04xn",
  351.        readw(&boot->signature));
  352. eicon_isa_release(card);
  353. return -EIO;
  354. }
  355. card->channels = readb(&card->shmem->c[0x3f6]);
  356. /* clear irq-requests, reset irq-count */
  357. readb(card->intack);
  358. writeb(0, card->intack);
  359. if (card->master) {
  360. card->irqprobe = 1;
  361. /* Trigger an interrupt and check if it is delivered */
  362. tmp = readb(&card->shmem->com.ReadyInt);
  363. tmp ++;
  364. writeb(tmp, &card->shmem->com.ReadyInt);
  365. timeout = jiffies + HZ / 5;
  366. while (time_before(jiffies, timeout)) {
  367. if (card->irqprobe > 1)
  368. break;
  369. SLEEP(2);
  370. }
  371. if (card->irqprobe == 1) {
  372. printk(KERN_WARNING "eicon_isa_load: IRQ # %d test failedn", card->irq);
  373. eicon_isa_release(card);
  374. return -EIO;
  375. }
  376. }
  377. #ifdef EICON_MCA_DEBUG
  378. printk(KERN_INFO "eicon_isa_load: IRQ # %d test succeeded.n", card->irq);
  379. #endif
  380. writeb(card->irq, &card->shmem->com.Int);
  381. /* initializing some variables */
  382. ((eicon_card *)card->card)->ReadyInt = 0;
  383. ((eicon_card *)card->card)->ref_in  = 1;
  384. ((eicon_card *)card->card)->ref_out = 1;
  385. for(j=0; j<256; j++) ((eicon_card *)card->card)->IdTable[j] = NULL;
  386. for(j=0; j< (card->channels + 1); j++) {
  387. ((eicon_card *)card->card)->bch[j].e.busy = 0;
  388. ((eicon_card *)card->card)->bch[j].e.D3Id = 0;
  389. ((eicon_card *)card->card)->bch[j].e.B2Id = 0;
  390. ((eicon_card *)card->card)->bch[j].e.ref = 0;
  391. ((eicon_card *)card->card)->bch[j].e.Req = 0;
  392. ((eicon_card *)card->card)->bch[j].e.complete = 1;
  393. ((eicon_card *)card->card)->bch[j].fsm_state = EICON_STATE_NULL;
  394. }
  395. printk(KERN_INFO "Eicon: Supported channels: %dn", card->channels); 
  396. printk(KERN_INFO "%s successfully startedn", eicon_ctype_name[card->type]);
  397. /* Enable normal IRQ processing */
  398. card->irqprobe = 0;
  399. return 0;
  400. }
  401. #endif /* CONFIG_ISDN_DRV_EICON_ISA */