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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: t1isa.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
  2.  * 
  3.  * Module for AVM T1 HEMA-card.
  4.  * 
  5.  * Copyright 1999 by Carsten Paeth <calle@calle.de>
  6.  * 
  7.  * This software may be used and distributed according to the terms
  8.  * of the GNU General Public License, incorporated herein by reference.
  9.  *
  10.  */
  11. #include <linux/module.h>
  12. #include <linux/kernel.h>
  13. #include <linux/skbuff.h>
  14. #include <linux/delay.h>
  15. #include <linux/mm.h>
  16. #include <linux/interrupt.h>
  17. #include <linux/ioport.h>
  18. #include <linux/capi.h>
  19. #include <linux/kernelcapi.h>
  20. #include <linux/init.h>
  21. #include <asm/io.h>
  22. #include "capicmd.h"
  23. #include "capiutil.h"
  24. #include "capilli.h"
  25. #include "avmcard.h"
  26. static char *revision = "$Revision: 1.1.4.1 $";
  27. /* ------------------------------------------------------------- */
  28. MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 HEMA ISA card");
  29. MODULE_AUTHOR("Carsten Paeth");
  30. MODULE_LICENSE("GPL");
  31. /* ------------------------------------------------------------- */
  32. static struct capi_driver_interface *di;
  33. /* ------------------------------------------------------------- */
  34. static int hema_irq_table[16] =
  35. {0,
  36.  0,
  37.  0,
  38.  0x80, /* irq 3 */
  39.  0,
  40.  0x90, /* irq 5 */
  41.  0,
  42.  0xA0, /* irq 7 */
  43.  0,
  44.  0xB0, /* irq 9 */
  45.  0xC0, /* irq 10 */
  46.  0xD0, /* irq 11 */
  47.  0xE0, /* irq 12 */
  48.  0,
  49.  0,
  50.  0xF0, /* irq 15 */
  51. };
  52. static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr)
  53. {
  54. unsigned char cregs[8];
  55. unsigned char reverse_cardnr;
  56. unsigned long flags;
  57. unsigned char dummy;
  58. int i;
  59. reverse_cardnr =   ((cardnr & 0x01) << 3) | ((cardnr & 0x02) << 1)
  60.          | ((cardnr & 0x04) >> 1) | ((cardnr & 0x08) >> 3);
  61. cregs[0] = (HEMA_VERSION_ID << 4) | (reverse_cardnr & 0xf);
  62. cregs[1] = 0x00; /* fast & slow link connected to CON1 */
  63. cregs[2] = 0x05; /* fast link 20MBit, slow link 20 MBit */
  64. cregs[3] = 0;
  65. cregs[4] = 0x11; /* zero wait state */
  66. cregs[5] = hema_irq_table[irq & 0xf];
  67. cregs[6] = 0;
  68. cregs[7] = 0;
  69. save_flags(flags);
  70. cli();
  71. /* board reset */
  72. t1outp(base, T1_RESETBOARD, 0xf);
  73. mdelay(100);
  74. dummy = t1inp(base, T1_FASTLINK+T1_OUTSTAT); /* first read */
  75. /* write config */
  76. dummy = (base >> 4) & 0xff;
  77. for (i=1;i<=0xf;i++) t1outp(base, i, dummy);
  78. t1outp(base, HEMA_PAL_ID & 0xf, dummy);
  79. t1outp(base, HEMA_PAL_ID >> 4, cregs[0]);
  80. for(i=1;i<7;i++) t1outp(base, 0, cregs[i]);
  81. t1outp(base, ((base >> 4)) & 0x3, cregs[7]);
  82. restore_flags(flags);
  83. mdelay(100);
  84. t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
  85. t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0);
  86. mdelay(10);
  87. t1outp(base, T1_FASTLINK+T1_RESETLINK, 1);
  88. t1outp(base, T1_SLOWLINK+T1_RESETLINK, 1);
  89. mdelay(100);
  90. t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
  91. t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0);
  92. mdelay(10);
  93. t1outp(base, T1_FASTLINK+T1_ANALYSE, 0);
  94. mdelay(5);
  95. t1outp(base, T1_SLOWLINK+T1_ANALYSE, 0);
  96. if (t1inp(base, T1_FASTLINK+T1_OUTSTAT) != 0x1) /* tx empty */
  97. return 1;
  98. if (t1inp(base, T1_FASTLINK+T1_INSTAT) != 0x0) /* rx empty */
  99. return 2;
  100. if (t1inp(base, T1_FASTLINK+T1_IRQENABLE) != 0x0)
  101. return 3;
  102. if ((t1inp(base, T1_FASTLINK+T1_FIFOSTAT) & 0xf0) != 0x70)
  103. return 4;
  104. if ((t1inp(base, T1_FASTLINK+T1_IRQMASTER) & 0x0e) != 0)
  105. return 5;
  106. if ((t1inp(base, T1_FASTLINK+T1_IDENT) & 0x7d) != 1)
  107. return 6;
  108. if (t1inp(base, T1_SLOWLINK+T1_OUTSTAT) != 0x1) /* tx empty */
  109. return 7;
  110. if ((t1inp(base, T1_SLOWLINK+T1_IRQMASTER) & 0x0e) != 0)
  111. return 8;
  112. if ((t1inp(base, T1_SLOWLINK+T1_IDENT) & 0x7d) != 0)
  113. return 9;
  114.         return 0;
  115. }
  116. static void t1_handle_interrupt(avmcard * card)
  117. {
  118. avmctrl_info *cinfo = &card->ctrlinfo[0];
  119. struct capi_ctr *ctrl = cinfo->capi_ctrl;
  120. unsigned char b1cmd;
  121. struct sk_buff *skb;
  122. unsigned ApplId;
  123. unsigned MsgLen;
  124. unsigned DataB3Len;
  125. unsigned NCCI;
  126. unsigned WindowSize;
  127. while (b1_rx_full(card->port)) {
  128. b1cmd = b1_get_byte(card->port);
  129. switch (b1cmd) {
  130. case RECEIVE_DATA_B3_IND:
  131. ApplId = (unsigned) b1_get_word(card->port);
  132. MsgLen = t1_get_slice(card->port, card->msgbuf);
  133. DataB3Len = t1_get_slice(card->port, card->databuf);
  134. if (MsgLen < 30) { /* not CAPI 64Bit */
  135. memset(card->msgbuf+MsgLen, 0, 30-MsgLen);
  136. MsgLen = 30;
  137. CAPIMSG_SETLEN(card->msgbuf, 30);
  138. }
  139. if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) {
  140. printk(KERN_ERR "%s: incoming packet droppedn",
  141. card->name);
  142. } else {
  143. memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
  144. memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len);
  145. ctrl->handle_capimsg(ctrl, ApplId, skb);
  146. }
  147. break;
  148. case RECEIVE_MESSAGE:
  149. ApplId = (unsigned) b1_get_word(card->port);
  150. MsgLen = t1_get_slice(card->port, card->msgbuf);
  151. if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
  152. printk(KERN_ERR "%s: incoming packet droppedn",
  153. card->name);
  154. } else {
  155. memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
  156. ctrl->handle_capimsg(ctrl, ApplId, skb);
  157. }
  158. break;
  159. case RECEIVE_NEW_NCCI:
  160. ApplId = b1_get_word(card->port);
  161. NCCI = b1_get_word(card->port);
  162. WindowSize = b1_get_word(card->port);
  163. ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize);
  164. break;
  165. case RECEIVE_FREE_NCCI:
  166. ApplId = b1_get_word(card->port);
  167. NCCI = b1_get_word(card->port);
  168. if (NCCI != 0xffffffff)
  169. ctrl->free_ncci(ctrl, ApplId, NCCI);
  170. else ctrl->appl_released(ctrl, ApplId);
  171. break;
  172. case RECEIVE_START:
  173. b1_put_byte(card->port, SEND_POLLACK);
  174. ctrl->resume_output(ctrl);
  175. break;
  176. case RECEIVE_STOP:
  177. ctrl->suspend_output(ctrl);
  178. break;
  179. case RECEIVE_INIT:
  180. cinfo->versionlen = t1_get_slice(card->port, cinfo->versionbuf);
  181. b1_parse_version(cinfo);
  182. printk(KERN_INFO "%s: %s-card (%s) now activen",
  183.        card->name,
  184.        cinfo->version[VER_CARDTYPE],
  185.        cinfo->version[VER_DRIVER]);
  186. ctrl->ready(ctrl);
  187. break;
  188. case RECEIVE_TASK_READY:
  189. ApplId = (unsigned) b1_get_word(card->port);
  190. MsgLen = t1_get_slice(card->port, card->msgbuf);
  191. card->msgbuf[MsgLen] = 0;
  192. while (    MsgLen > 0
  193.        && (   card->msgbuf[MsgLen-1] == 'n'
  194.    || card->msgbuf[MsgLen-1] == 'r')) {
  195. card->msgbuf[MsgLen-1] = 0;
  196. MsgLen--;
  197. }
  198. printk(KERN_INFO "%s: task %d "%s" ready.n",
  199. card->name, ApplId, card->msgbuf);
  200. break;
  201. case RECEIVE_DEBUGMSG:
  202. MsgLen = t1_get_slice(card->port, card->msgbuf);
  203. card->msgbuf[MsgLen] = 0;
  204. while (    MsgLen > 0
  205.        && (   card->msgbuf[MsgLen-1] == 'n'
  206.    || card->msgbuf[MsgLen-1] == 'r')) {
  207. card->msgbuf[MsgLen-1] = 0;
  208. MsgLen--;
  209. }
  210. printk(KERN_INFO "%s: DEBUG: %sn", card->name, card->msgbuf);
  211. break;
  212. case 0xff:
  213. printk(KERN_ERR "%s: card reseted ?n", card->name);
  214. return;
  215. default:
  216. printk(KERN_ERR "%s: b1_interrupt: 0x%x ???n",
  217. card->name, b1cmd);
  218. return;
  219. }
  220. }
  221. }
  222. /* ------------------------------------------------------------- */
  223. static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
  224. {
  225. avmcard *card;
  226. card = (avmcard *) devptr;
  227. if (!card) {
  228. printk(KERN_WARNING "t1isa: interrupt: wrong devicen");
  229. return;
  230. }
  231. if (card->interrupt) {
  232. printk(KERN_ERR "%s: reentering interrupt hander.n",
  233.  card->name);
  234. return;
  235. }
  236. card->interrupt = 1;
  237. t1_handle_interrupt(card);
  238. card->interrupt = 0;
  239. }
  240. /* ------------------------------------------------------------- */
  241. static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
  242. {
  243. avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
  244. avmcard *card = cinfo->card;
  245. unsigned int port = card->port;
  246. unsigned long flags;
  247. int retval;
  248. t1_disable_irq(port);
  249. b1_reset(port);
  250. if ((retval = b1_load_t4file(card, &data->firmware))) {
  251. b1_reset(port);
  252. printk(KERN_ERR "%s: failed to load t4file!!n",
  253. card->name);
  254. return retval;
  255. }
  256. if (data->configuration.len > 0 && data->configuration.data) {
  257. if ((retval = b1_load_config(card, &data->configuration))) {
  258. b1_reset(port);
  259. printk(KERN_ERR "%s: failed to load config!!n",
  260. card->name);
  261. return retval;
  262. }
  263. }
  264. if (!b1_loaded(card)) {
  265. printk(KERN_ERR "%s: failed to load t4file.n", card->name);
  266. return -EIO;
  267. }
  268. save_flags(flags);
  269. cli();
  270. b1_setinterrupt(port, card->irq, card->cardtype);
  271. b1_put_byte(port, SEND_INIT);
  272. b1_put_word(port, CAPI_MAXAPPL);
  273. b1_put_word(port, AVM_NCCI_PER_CHANNEL*30);
  274. b1_put_word(port, ctrl->cnr - 1);
  275. restore_flags(flags);
  276. return 0;
  277. }
  278. void t1isa_reset_ctr(struct capi_ctr *ctrl)
  279. {
  280. avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
  281. avmcard *card = cinfo->card;
  282. unsigned int port = card->port;
  283. t1_disable_irq(port);
  284. b1_reset(port);
  285. b1_reset(port);
  286. memset(cinfo->version, 0, sizeof(cinfo->version));
  287. ctrl->reseted(ctrl);
  288. }
  289. static void t1isa_remove_ctr(struct capi_ctr *ctrl)
  290. {
  291. avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
  292. avmcard *card = cinfo->card;
  293. unsigned int port = card->port;
  294. t1_disable_irq(port);
  295. b1_reset(port);
  296. b1_reset(port);
  297. t1_reset(port);
  298. di->detach_ctr(ctrl);
  299. free_irq(card->irq, card);
  300. release_region(card->port, AVMB1_PORTLEN);
  301. kfree(card->ctrlinfo);
  302. kfree(card);
  303. MOD_DEC_USE_COUNT;
  304. }
  305. /* ------------------------------------------------------------- */
  306. static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
  307. {
  308. struct capi_ctr *ctrl;
  309. avmctrl_info *cinfo;
  310. avmcard *card;
  311. int retval;
  312. MOD_INC_USE_COUNT;
  313. card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
  314. if (!card) {
  315. printk(KERN_WARNING "%s: no memory.n", driver->name);
  316.         MOD_DEC_USE_COUNT;
  317. return -ENOMEM;
  318. }
  319. memset(card, 0, sizeof(avmcard));
  320.         cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC);
  321. if (!cinfo) {
  322. printk(KERN_WARNING "%s: no memory.n", driver->name);
  323. kfree(card);
  324.         MOD_DEC_USE_COUNT;
  325. return -ENOMEM;
  326. }
  327. memset(cinfo, 0, sizeof(avmctrl_info));
  328. card->ctrlinfo = cinfo;
  329. cinfo->card = card;
  330. sprintf(card->name, "t1isa-%x", p->port);
  331. card->port = p->port;
  332. card->irq = p->irq;
  333. card->cardtype = avm_t1isa;
  334. card->cardnr = p->cardnr;
  335. if (!(((card->port & 0x7) == 0) && ((card->port & 0x30) != 0x30))) {
  336. printk(KERN_WARNING "%s: illegal port 0x%x.n",
  337. driver->name, card->port);
  338.         kfree(card->ctrlinfo);
  339. kfree(card);
  340.         MOD_DEC_USE_COUNT;
  341. return -EINVAL;
  342.         }
  343. if (check_region(card->port, AVMB1_PORTLEN)) {
  344. printk(KERN_WARNING
  345.        "%s: ports 0x%03x-0x%03x in use.n",
  346.        driver->name, card->port, card->port + AVMB1_PORTLEN);
  347.         kfree(card->ctrlinfo);
  348. kfree(card);
  349.         MOD_DEC_USE_COUNT;
  350. return -EBUSY;
  351. }
  352. if (hema_irq_table[card->irq & 0xf] == 0) {
  353. printk(KERN_WARNING "%s: irq %d not valid.n",
  354. driver->name, card->irq);
  355.         kfree(card->ctrlinfo);
  356. kfree(card);
  357.         MOD_DEC_USE_COUNT;
  358. return -EINVAL;
  359. }
  360. for (ctrl = driver->controller; ctrl; ctrl = ctrl->next) {
  361.         avmcard *cardp = ((avmctrl_info *)(ctrl->driverdata))->card;
  362. if (cardp->cardnr == card->cardnr) {
  363. printk(KERN_WARNING "%s: card with number %d already installed at 0x%x.n",
  364. driver->name, card->cardnr, cardp->port);
  365.                 kfree(card->ctrlinfo);
  366. kfree(card);
  367.          MOD_DEC_USE_COUNT;
  368. return -EBUSY;
  369. }
  370. }
  371.         if ((retval = t1_detectandinit(card->port, card->irq, card->cardnr)) != 0) {
  372. printk(KERN_NOTICE "%s: NO card at 0x%x (%d)n",
  373. driver->name, card->port, retval);
  374.         kfree(card->ctrlinfo);
  375. kfree(card);
  376. MOD_DEC_USE_COUNT;
  377. return -EIO;
  378. }
  379. t1_disable_irq(card->port);
  380. b1_reset(card->port);
  381. request_region(p->port, AVMB1_PORTLEN, card->name);
  382. retval = request_irq(card->irq, t1isa_interrupt, 0, card->name, card);
  383. if (retval) {
  384. printk(KERN_ERR "%s: unable to get IRQ %d.n",
  385. driver->name, card->irq);
  386. release_region(card->port, AVMB1_PORTLEN);
  387.         kfree(card->ctrlinfo);
  388. kfree(card);
  389. MOD_DEC_USE_COUNT;
  390. return -EBUSY;
  391. }
  392. cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo);
  393. if (!cinfo->capi_ctrl) {
  394. printk(KERN_ERR "%s: attach controller failed.n",
  395. driver->name);
  396. free_irq(card->irq, card);
  397. release_region(card->port, AVMB1_PORTLEN);
  398.         kfree(card->ctrlinfo);
  399. kfree(card);
  400. MOD_DEC_USE_COUNT;
  401. return -EBUSY;
  402. }
  403. printk(KERN_INFO
  404. "%s: AVM T1 ISA at i/o %#x, irq %d, card %dn",
  405. driver->name, card->port, card->irq, card->cardnr);
  406. return 0;
  407. }
  408. static void t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
  409. {
  410. avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
  411. avmcard *card = cinfo->card;
  412. unsigned int port = card->port;
  413. unsigned long flags;
  414. __u16 len = CAPIMSG_LEN(skb->data);
  415. __u8 cmd = CAPIMSG_COMMAND(skb->data);
  416. __u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
  417. save_flags(flags);
  418. cli();
  419. if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
  420. __u16 dlen = CAPIMSG_DATALEN(skb->data);
  421. b1_put_byte(port, SEND_DATA_B3_REQ);
  422. t1_put_slice(port, skb->data, len);
  423. t1_put_slice(port, skb->data + len, dlen);
  424. } else {
  425. b1_put_byte(port, SEND_MESSAGE);
  426. t1_put_slice(port, skb->data, len);
  427. }
  428. restore_flags(flags);
  429. dev_kfree_skb(skb);
  430. }
  431. /* ------------------------------------------------------------- */
  432. static char *t1isa_procinfo(struct capi_ctr *ctrl)
  433. {
  434. avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
  435. if (!cinfo)
  436. return "";
  437. sprintf(cinfo->infobuf, "%s %s 0x%x %d %d",
  438. cinfo->cardname[0] ? cinfo->cardname : "-",
  439. cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
  440. cinfo->card ? cinfo->card->port : 0x0,
  441. cinfo->card ? cinfo->card->irq : 0,
  442. cinfo->card ? cinfo->card->cardnr : 0
  443. );
  444. return cinfo->infobuf;
  445. }
  446. /* ------------------------------------------------------------- */
  447. static struct capi_driver t1isa_driver = {
  448.     name: "t1isa",
  449.     revision: "0.0",
  450.     load_firmware: t1isa_load_firmware,
  451.     reset_ctr: t1isa_reset_ctr,
  452.     remove_ctr: t1isa_remove_ctr,
  453.     register_appl: b1_register_appl,
  454.     release_appl: b1_release_appl,
  455.     send_message: t1isa_send_message,
  456.     procinfo: t1isa_procinfo,
  457.     ctr_read_proc: b1ctl_read_proc,
  458.     driver_read_proc: 0, /* use standard driver_read_proc */
  459.     add_card: t1isa_add_card,
  460. };
  461. static int __init t1isa_init(void)
  462. {
  463. struct capi_driver *driver = &t1isa_driver;
  464. char *p;
  465. int retval = 0;
  466. MOD_INC_USE_COUNT;
  467. if ((p = strchr(revision, ':')) != 0 && p[1]) {
  468. strncpy(driver->revision, p + 2, sizeof(driver->revision));
  469. driver->revision[sizeof(driver->revision)-1] = 0;
  470. if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision)
  471. *(p-1) = 0;
  472. }
  473. printk(KERN_INFO "%s: revision %sn", driver->name, driver->revision);
  474.         di = attach_capi_driver(driver);
  475. if (!di) {
  476. printk(KERN_ERR "%s: failed to attach capi_drivern",
  477. driver->name);
  478. retval = -EIO;
  479. }
  480. MOD_DEC_USE_COUNT;
  481. return retval;
  482. }
  483. static void __exit t1isa_exit(void)
  484. {
  485.     detach_capi_driver(&t1isa_driver);
  486. }
  487. module_init(t1isa_init);
  488. module_exit(t1isa_exit);