tpam_commands.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:27k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: tpam_commands.c,v 1.1.2.1 2001/11/20 14:19:37 kai Exp $
  2.  *
  3.  * Turbo PAM ISDN driver for Linux. (Kernel Driver - ISDN commands)
  4.  *
  5.  * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alc魐e
  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.  * For all support questions please contact: <support@auvertech.fr>
  11.  *
  12.  */
  13. #include <linux/module.h>
  14. #include <linux/pci.h>
  15. #include <linux/sched.h>
  16. #include <linux/tqueue.h>
  17. #include <linux/interrupt.h>
  18. #include <asm/io.h>
  19. #include <linux/isdn/tpam.h>
  20. #include "tpam.h"
  21. /* Local functions prototypes */
  22. static int tpam_command_ioctl_dspload(tpam_card *, u32);
  23. static int tpam_command_ioctl_dspsave(tpam_card *, u32);
  24. static int tpam_command_ioctl_dsprun(tpam_card *);
  25. static int tpam_command_ioctl_loopmode(tpam_card *, u8);
  26. static int tpam_command_dial(tpam_card *, u32, u8 *);
  27. static int tpam_command_setl2(tpam_card *, u32, u8);
  28. static int tpam_command_getl2(tpam_card *, u32);
  29. static int tpam_command_acceptd(tpam_card *, u32);
  30. static int tpam_command_acceptb(tpam_card *, u32);
  31. static int tpam_command_hangup(tpam_card *, u32);
  32. static int tpam_command_proceed(tpam_card *, u32);
  33. static void tpam_statcallb_run(unsigned long);
  34. static void tpam_statcallb(tpam_card *, isdn_ctrl);
  35. /*
  36.  * Function called when the ISDN link level send a command to the driver.
  37.  *
  38.  *  c: ISDN command.
  39.  *
  40.  * Return: 0 if OK, <0 on errors.
  41.  */
  42. int tpam_command(isdn_ctrl *c) {
  43. tpam_card *card;
  44. unsigned long argp;
  45. dprintk("TurboPAM(tpam_command) card=%d, command=%dn", 
  46. c->driver, c->command);
  47. /* search for the board */
  48. if (!(card = tpam_findcard(c->driver))) {
  49. printk(KERN_ERR "TurboPAM(tpam_command): invalid driverId %dn",
  50.        c->driver);
  51. return -ENODEV;
  52. }
  53. /* dispatch the command */
  54. switch (c->command) {
  55. case ISDN_CMD_IOCTL:
  56. argp = c->parm.userdata;
  57. switch (c->arg) {
  58. case TPAM_CMD_DSPLOAD:
  59. return tpam_command_ioctl_dspload(card,
  60.   argp);
  61. case TPAM_CMD_DSPSAVE:
  62. return tpam_command_ioctl_dspsave(card,
  63.   argp);
  64. case TPAM_CMD_DSPRUN:
  65. return tpam_command_ioctl_dsprun(card);
  66. case TPAM_CMD_LOOPMODEON:
  67. return tpam_command_ioctl_loopmode(card,
  68.    1);
  69. case TPAM_CMD_LOOPMODEOFF:
  70. return tpam_command_ioctl_loopmode(card,
  71.    0);
  72. default:
  73. dprintk("TurboPAM(tpam_command): "
  74. "invalid tpam ioctl %ldn", 
  75. c->arg);
  76. return -EINVAL;
  77. }
  78. case ISDN_CMD_DIAL:
  79. return tpam_command_dial(card, c->arg, 
  80.  c->parm.setup.phone);
  81. case ISDN_CMD_ACCEPTD:
  82. return tpam_command_acceptd(card, c->arg);
  83. case ISDN_CMD_ACCEPTB:
  84. return tpam_command_acceptb(card, c->arg);
  85. case ISDN_CMD_HANGUP:
  86. return tpam_command_hangup(card, c->arg);
  87. case ISDN_CMD_SETL2:
  88. return tpam_command_setl2(card, c->arg & 0xff, 
  89.   c->arg >> 8);
  90. case ISDN_CMD_GETL2:
  91. return tpam_command_getl2(card, c->arg);
  92. case ISDN_CMD_LOCK:
  93. MOD_INC_USE_COUNT;
  94. return 0;
  95. case ISDN_CMD_UNLOCK:
  96. MOD_DEC_USE_COUNT;
  97. return 0;
  98. case ISDN_CMD_PROCEED:
  99. return tpam_command_proceed(card, c->arg);
  100. default:
  101. dprintk("TurboPAM(tpam_command): "
  102. "unknown or unused isdn ioctl %dn", 
  103. c->command);
  104. return -EINVAL;
  105. }
  106. /* not reached */
  107. return -EINVAL;
  108. }
  109. /*
  110.  * Load some data into the board's memory.
  111.  *
  112.  *  card: the board
  113.  *  arg: IOCTL argument containing the user space address of 
  114.  *  the tpam_dsp_ioctl structure describing the IOCTL.
  115.  *
  116.  * Return: 0 if OK, <0 on errors.
  117.  */
  118. static int tpam_command_ioctl_dspload(tpam_card *card, u32 arg) {
  119. tpam_dsp_ioctl tdl;
  120. int ret;
  121. dprintk("TurboPAM(tpam_command_ioctl_dspload): card=%dn", card->id);
  122. /* get the IOCTL parameter from userspace */
  123. if (copy_from_user(&tdl, (void *)arg, sizeof(tpam_dsp_ioctl)))
  124. return -EFAULT;
  125. /* if the board's firmware was started, protect against writes
  126.  * to unallowed memory areas. If the board's firmware wasn't started,
  127.  * all is allowed. */
  128. if (card->running && tpam_verify_area(tdl.address, tdl.data_len)) 
  129. return -EPERM;
  130. /* write the data in the board's memory */
  131. ret = copy_from_user_to_pam(card, (void *)tdl.address, 
  132.     (void *)arg + sizeof(tpam_dsp_ioctl), 
  133.     tdl.data_len);
  134. return 0;
  135. }
  136. /*
  137.  * Extract some data from the board's memory.
  138.  *
  139.  *  card: the board
  140.  *  arg: IOCTL argument containing the user space address of 
  141.  *  the tpam_dsp_ioctl structure describing the IOCTL.
  142.  *
  143.  * Return: 0 if OK, <0 on errors.
  144.  */
  145. static int tpam_command_ioctl_dspsave(tpam_card *card, u32 arg) {
  146. tpam_dsp_ioctl tdl;
  147. int ret;
  148. dprintk("TurboPAM(tpam_command_ioctl_dspsave): card=%dn", card->id);
  149. /* get the IOCTL parameter from userspace */
  150. if (copy_from_user(&tdl, (void *)arg, sizeof(tpam_dsp_ioctl)))
  151. return -EFAULT;
  152. /* protect against read from unallowed memory areas */
  153. if (tpam_verify_area(tdl.address, tdl.data_len)) 
  154. return -EPERM;
  155. /* read the data from the board's memory */
  156. ret = copy_from_pam_to_user(card, (void *)arg + sizeof(tpam_dsp_ioctl),
  157.     (void *)tdl.address, tdl.data_len);
  158. return ret;
  159. }
  160. /*
  161.  * Launch the board's firmware. This function must be called after the 
  162.  * firmware was loaded into the board's memory using TPAM_CMD_DSPLOAD 
  163.  * IOCTL commands. After launching the firmware, this function creates
  164.  * the NCOs and waits for their creation.
  165.  *
  166.  *  card: the board
  167.  *
  168.  * Return: 0 if OK, <0 on errors.
  169.  */
  170. static int tpam_command_ioctl_dsprun(tpam_card *card) {
  171. u32 signature = 0, timeout, i;
  172. isdn_ctrl ctrl;
  173. struct sk_buff *skb;
  174. dprintk("TurboPAM(tpam_command_ioctl_dsprun): card=%dn", card->id);
  175. /* board must _not_ be running */
  176. if (card->running)
  177. return -EBUSY;
  178. /* reset the board */
  179. spin_lock_irq(&card->lock);
  180. copy_to_pam_dword(card, (void *)TPAM_MAGICNUMBER_REGISTER, 0xdeadface);
  181. readl(card->bar0 + TPAM_DSPINT_REGISTER);
  182. readl(card->bar0 + TPAM_HINTACK_REGISTER);
  183. spin_unlock_irq(&card->lock);
  184. /* wait for the board signature */
  185. timeout = jiffies + SIGNATURE_TIMEOUT;
  186. while (time_before(jiffies, timeout)) {
  187. spin_lock_irq(&card->lock);
  188. signature = copy_from_pam_dword(card, 
  189. (void *)TPAM_MAGICNUMBER_REGISTER);
  190. spin_unlock_irq(&card->lock);
  191. if (signature == TPAM_MAGICNUMBER)
  192. break;
  193. set_current_state(TASK_UNINTERRUPTIBLE);
  194. schedule_timeout(2);
  195. }
  196. /* signature not present -> board not started */
  197. if (signature != TPAM_MAGICNUMBER) {
  198. printk(KERN_ERR "TurboPAM(tpam_command_ioctl_dsprun): "
  199.        "card=%d, signature 0x%lx, expected 0x%lxn", 
  200.        card->id, (unsigned long)signature, 
  201.        (unsigned long)TPAM_MAGICNUMBER);
  202. printk(KERN_ERR "TurboPAM(tpam_command_ioctl_dsprun): "
  203.        "card=%d, firmware not startedn", card->id);
  204. return -EIO;
  205. }
  206. /* the firmware is started */
  207. printk(KERN_INFO "TurboPAM: card=%d, firmware startedn", card->id);
  208. /* init the CRC routines */
  209. init_CRC();
  210. /* create all the NCOs */
  211. for (i = 0; i < TPAM_NBCHANNEL; ++i)
  212. if ((skb = build_ACreateNCOReq("")))
  213. tpam_enqueue(card, skb);
  214. /* wait for NCO creation confirmation */
  215. timeout = jiffies + NCOCREATE_TIMEOUT;
  216. while (time_before(jiffies, timeout)) {
  217. if (card->channels_tested == TPAM_NBCHANNEL)
  218. break;
  219. set_current_state(TASK_UNINTERRUPTIBLE);
  220. schedule_timeout(2);
  221. }
  222. card->running = 1;
  223. if (card->channels_tested != TPAM_NBCHANNEL)
  224. printk(KERN_ERR "TurboPAM(tpam_command_ioctl_dsprun): "
  225.        "card=%d, tried to init %d channels, "
  226.        "got reply from only %d channelsn", card->id, 
  227.        TPAM_NBCHANNEL, card->channels_tested);
  228. /* if all the channels were not initialized, signal to the ISDN
  229.  * link layer that fact that some channels are not usable */
  230. if (card->channels_used != TPAM_NBCHANNEL)
  231. for (i = card->channels_used; i < TPAM_NBCHANNEL; ++i) {
  232. ctrl.driver = card->id;
  233. ctrl.command = ISDN_STAT_DISCH;
  234. ctrl.arg = i;
  235. ctrl.parm.num[0] = 0;
  236. (* card->interface.statcallb)(&ctrl);
  237. }
  238. printk(KERN_INFO "TurboPAM: card=%d, ready, %d channels availablen", 
  239.        card->id, card->channels_used);
  240. /* let's rock ! */
  241. ctrl.driver = card->id;
  242. ctrl.command = ISDN_STAT_RUN;
  243. ctrl.arg = 0;
  244. tpam_statcallb(card, ctrl);
  245. return 0;
  246. }
  247. /* 
  248.  * Set/reset the board's looptest mode.
  249.  *
  250.  *  card: the board
  251.  *  mode: if 1, sets the board's looptest mode, if 0 resets it.
  252.  *
  253.  * Return: 0 if OK, <0 if error.
  254.  */
  255. static int tpam_command_ioctl_loopmode(tpam_card *card, u8 mode) {
  256. /* board must be running */
  257. if (!card->running)
  258. return -ENODEV;
  259. card->loopmode = mode;
  260. return 0;
  261. }
  262. /*
  263.  * Issue a dial command. This function builds and sends a CConnectReq.
  264.  * 
  265.  *  card: the board
  266.  *  channel: the channel number
  267.  *  phone: the remote phone number (EAZ)
  268.  *
  269.  * Return: 0 if OK, <0 if error.
  270.  */
  271. static int tpam_command_dial(tpam_card *card, u32 channel, u8 *phone) {
  272. struct sk_buff *skb;
  273. isdn_ctrl ctrl;
  274. dprintk("TurboPAM(tpam_command_dial): card=%d, channel=%lu, phone=%sn",
  275. card->id, (unsigned long)channel, phone);
  276. /* board must be running */
  277. if (!card->running)
  278. return -ENODEV;
  279. /* initialize channel parameters */
  280. card->channels[channel].realhdlc = card->channels[channel].hdlc;
  281. card->channels[channel].hdlcshift = 0;
  282. card->channels[channel].readytoreceive = 0;
  283. /* build and send a CConnectReq */
  284. skb = build_CConnectReq(card->channels[channel].ncoid, phone, 
  285. card->channels[channel].realhdlc);
  286. if (!skb)
  287. return -ENOMEM;
  288. tpam_enqueue(card, skb);
  289. /* making a connection in modem mode is slow and causes the ISDN
  290.  * link layer to hangup the connection before even it gets a chance
  291.  * to establish... All we can do is simulate a successful connection
  292.  * for now, and send a DHUP later if the connection fails */
  293. if (!card->channels[channel].realhdlc) {
  294. ctrl.driver = card->id;
  295. ctrl.command = ISDN_STAT_DCONN;
  296. ctrl.arg = channel;
  297. tpam_statcallb(card, ctrl);
  298. }
  299. return 0;
  300. }
  301. /*
  302.  * Set the level2 protocol (modem or HDLC).
  303.  *
  304.  *  card: the board
  305.  *  channel: the channel number
  306.  *  proto: the level2 protocol (one of ISDN_PROTO_L2*)
  307.  *
  308.  * Return: 0 if OK, <0 if error.
  309.  */
  310. static int tpam_command_setl2(tpam_card *card, u32 channel, u8 proto) {
  311. dprintk("TurboPAM(tpam_command_setl2): card=%d, channel=%lu, proto=%dn",
  312. card->id, (unsigned long)channel, proto);
  313. /* board must be running */
  314. if (!card->running)
  315. return -ENODEV;
  316. /* set the hdlc/modem mode */
  317. switch (proto) {
  318. case ISDN_PROTO_L2_HDLC:
  319. card->channels[channel].hdlc = 1;
  320. break;
  321. case ISDN_PROTO_L2_MODEM:
  322. card->channels[channel].hdlc = 0;
  323. break;
  324. default:
  325. return -EINVAL;
  326. }
  327. return 0;
  328. }
  329. /*
  330.  * Return the level2 protocol (modem or HDLC).
  331.  *
  332.  *  card: the board
  333.  *  channel: the channel number
  334.  *
  335.  * Return: ISDN_PROTO_L2_HDLC/MODEM if OK, <0 if error.
  336.  */
  337. static int tpam_command_getl2(tpam_card *card, u32 channel) {
  338. dprintk("TurboPAM(tpam_command_getl2): card=%d, channel=%lun",
  339. card->id, (unsigned long)channel);
  340. /* board must be running */
  341. if (!card->running)
  342. return -ENODEV;
  343. /* return the current mode */
  344. if (card->channels[channel].realhdlc)
  345. return ISDN_PROTO_L2_HDLC;
  346. else
  347. return ISDN_PROTO_L2_MODEM;
  348. }
  349. /*
  350.  * Accept a D-channel connection (incoming connection). This function
  351.  * builds and sends a CConnectRsp message and signals DCONN to the ISDN
  352.  * link level.
  353.  *
  354.  *  card: the board
  355.  *  channel: the channel number
  356.  *
  357.  * Return: 0 if OK, <0 if error.
  358.  */
  359. static int tpam_command_acceptd(tpam_card *card, u32 channel) {
  360. isdn_ctrl ctrl;
  361. struct sk_buff *skb;
  362. dprintk("TurboPAM(tpam_command_acceptd): card=%d, channel=%lun",
  363. card->id, (unsigned long)channel);
  364. /* board must be running */
  365. if (!card->running)
  366. return -ENODEV;
  367. /* build and send a CConnectRsp */
  368. skb = build_CConnectRsp(card->channels[channel].ncoid);
  369. if (!skb)
  370. return -ENOMEM;
  371. tpam_enqueue(card, skb);
  372. /* issue DCONN to the ISDN link level */
  373. ctrl.driver = card->id;
  374. ctrl.command = ISDN_STAT_DCONN;
  375. ctrl.arg = channel;
  376. tpam_statcallb(card, ctrl);
  377. return 0;
  378. }
  379. /*
  380.  * Accepts a B-channel connection. This is not used by the driver, 
  381.  * since the TurboPAM is an active card hiding its B-channels from
  382.  * us. We just signal BCONN to the ISDN link layer.
  383.  *
  384.  *  card: the board
  385.  *  channel: the channel number
  386.  *
  387.  * Return: 0 if OK, <0 if error.
  388.  */
  389. static int tpam_command_acceptb(tpam_card *card, u32 channel) {
  390. isdn_ctrl ctrl;
  391. dprintk("TurboPAM(tpam_command_acceptb): card=%d, channel=%lun",
  392. card->id, (unsigned long)channel);
  393. /* board must be running */
  394. if (!card->running)
  395. return -ENODEV;
  396. /* issue BCONN to the ISDN link level */
  397. ctrl.driver = card->id;
  398. ctrl.command = ISDN_STAT_BCONN;
  399. ctrl.arg = channel;
  400. ctrl.parm.num[0] = '';
  401. tpam_statcallb(card, ctrl);
  402. return 0;
  403. }
  404. /*
  405.  * Hang up a connection. This function builds and sends a CDisconnectReq.
  406.  *
  407.  *  card: the board
  408.  *  channel: the channel number.
  409.  *
  410.  * Return: 0 if OK, <0 if error.
  411.  */
  412. static int tpam_command_hangup(tpam_card *card, u32 channel) {
  413. struct sk_buff *skb;
  414. dprintk("TurboPAM(tpam_command_hangup): card=%d, channel=%lun",
  415. card->id, (unsigned long)channel);
  416. /* board must be running */
  417. if (!card->running)
  418. return -ENODEV;
  419. /* build and send a CDisconnectReq */
  420. skb = build_CDisconnectReq(card->channels[channel].ncoid);
  421. if (!skb)
  422. return -ENOMEM;
  423. tpam_enqueue(card, skb);
  424. return 0;
  425. }
  426. /*
  427.  * Proceed with an incoming connection. This function builds and sends a 
  428.  * CConnectRsp.
  429.  *
  430.  *  card: the board
  431.  *  channel: the channel number.
  432.  *
  433.  * Return: 0 if OK, <0 if error.
  434.  */
  435. static int tpam_command_proceed(tpam_card *card, u32 channel) {
  436. struct sk_buff *skb;
  437. dprintk("TurboPAM(tpam_command_proceed): card=%d, channel=%lun",
  438. card->id, (unsigned long)channel);
  439. /* board must be running */
  440. if (!card->running)
  441. return -ENODEV;
  442. /* build and send a CConnectRsp */
  443. skb = build_CConnectRsp(card->channels[channel].ncoid);
  444. if (!skb)
  445. return -ENOMEM;
  446. tpam_enqueue(card, skb);
  447. return 0;
  448. }
  449. /*
  450.  * Send data through the board. This function encodes the data depending
  451.  * on the connection type (modem or HDLC), then builds and sends a U3DataReq.
  452.  *
  453.  *  driverId: the driver id (really meaning here the board)
  454.  *  channel: the channel number
  455.  *  ack: data needs to be acknowledged upon send
  456.  *  skb: sk_buff containing the data
  457.  *
  458.  * Return: size of data send if OK, <0 if error.
  459.  */
  460. int tpam_writebuf_skb(int driverId, int channel, int ack, struct sk_buff *skb) {
  461. tpam_card *card;
  462. int orig_size = skb->len;
  463. void *finaldata;
  464. u32 finallen;
  465. dprintk("TurboPAM(tpam_writebuf_skb): "
  466. "card=%d, channel=%ld, ack=%d, data size=%dn", 
  467. driverId, (unsigned long)channel, ack, skb->len);
  468. /* find the board based on its driver ID */
  469. if (!(card = tpam_findcard(driverId))) {
  470. printk(KERN_ERR "TurboPAM(tpam_writebuf_skb): "
  471.        "invalid driverId %dn", driverId);
  472. return -ENODEV;
  473. }
  474. /* board must be running */
  475. if (!card->running)
  476. return -ENODEV;
  477. /* allocate some temporary memory */
  478. if (!(finaldata = (void *)__get_free_page(GFP_ATOMIC))) {
  479. printk(KERN_ERR "TurboPAM(tpam_writebuf_skb): "
  480.        "get_free_page failedn");
  481. return -ENOMEM;
  482. }
  483. /* encode the data */
  484. if (!card->channels[channel].realhdlc) {
  485. /* modem mode */
  486. hdlc_encode_modem(skb->data, skb->len, finaldata, &finallen);
  487. }
  488. else {
  489. /* HDLC mode */
  490. void *tempdata;
  491. u32 templen;
  492. if (!(tempdata = (void *)__get_free_page(GFP_ATOMIC))) {
  493. printk(KERN_ERR "TurboPAM(tpam_writebuf_skb): "
  494.        "get_free_page failedn");
  495. free_page((u32)finaldata);
  496. return -ENOMEM;
  497. }
  498. hdlc_no_accm_encode(skb->data, skb->len, tempdata, &templen);
  499. finallen = tpam_hdlc_encode(tempdata, finaldata, 
  500.        &card->channels[channel].hdlcshift, 
  501.        templen);
  502. free_page((u32)tempdata);
  503. }
  504. /* free the old sk_buff */
  505. kfree_skb(skb);
  506. /* build and send a U3DataReq */
  507. skb = build_U3DataReq(card->channels[channel].ncoid, finaldata, 
  508.       finallen, ack, orig_size);
  509. if (!skb) {
  510. free_page((u32)finaldata);
  511. return -ENOMEM;
  512. }
  513. tpam_enqueue_data(&card->channels[channel], skb);
  514. /* free the temporary memory */
  515. free_page((u32)finaldata);
  516. return orig_size;
  517. }
  518. /*
  519.  * Treat a received ACreateNCOCnf message.
  520.  *
  521.  *  card: the board
  522.  *  skb: the received message
  523.  */
  524. void tpam_recv_ACreateNCOCnf(tpam_card *card, struct sk_buff *skb) {
  525. u32 ncoid;
  526. u8 status;
  527. u32 channel;
  528. dprintk("TurboPAM(tpam_recv_ACreateNCOCnf): card=%dn", card->id);
  529. /* parse the message contents */
  530. if (parse_ACreateNCOCnf(skb, &status, &ncoid))
  531. return;
  532. /* if the card is alreay running, it means that this message
  533.  * arrives too late... */
  534. if (card->running) {
  535. printk(KERN_ERR "TurboPAM(tpam_recv_ACreateNCOCnf): "
  536.        "ACreateNCOCnf received too late, status=%dn", status);
  537. return;
  538. }
  539. /* the NCO creation failed, the corresponding channel will
  540.  * be unused */
  541. if (status) {
  542. printk(KERN_ERR "TurboPAM(tpam_recv_ACreateNCOCnf): "
  543.        "ACreateNCO failed, status=%dn", status);
  544. card->channels_tested++;
  545. return;
  546. }
  547. /* find the first free channel and assign the nco ID to it */
  548. if ((channel = tpam_findchannel(card, TPAM_NCOID_INVALID)) == TPAM_CHANNEL_INVALID) {
  549. printk(KERN_ERR "TurboPAM(tpam_recv_ACreateNCOCnf): "
  550.        "All channels are assignedn");
  551. return;
  552. }
  553. card->channels[channel].ncoid = ncoid;
  554. card->channels_tested++;
  555. card->channels_used++;
  556. }
  557. /*
  558.  * Treat a received ADestroyNCOCnf message. Not used by the driver.
  559.  *
  560.  *  card: the board
  561.  *  skb: the received message
  562.  */
  563. void tpam_recv_ADestroyNCOCnf(tpam_card *card, struct sk_buff *skb) {
  564. u32 ncoid;
  565. u8 status;
  566. u32 channel;
  567. dprintk("TurboPAM(tpam_recv_ADestroyNCOCnf): card=%dn", card->id);
  568. /* parse the message contents */
  569. if (parse_ADestroyNCOCnf(skb, &status, &ncoid))
  570. return;
  571. if (status) {
  572. printk(KERN_ERR "TurboPAM(tpam_recv_ADestroyNCOCnf): "
  573.        "ADestroyNCO failed, status=%dn", status);
  574. return;
  575. }
  576. /* clears the channel's nco ID */
  577. if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
  578. printk(KERN_ERR "TurboPAM(tpam_recv_ADestroyNCOCnf): "
  579.        "ncoid invalid %lun", (unsigned long)ncoid);
  580. return;
  581. }
  582. card->channels[channel].ncoid = TPAM_NCOID_INVALID;
  583. }
  584. /*
  585.  * Treat a received CConnectCnf message.
  586.  *
  587.  *  card: the board
  588.  *  skb: the received message
  589.  */
  590. void tpam_recv_CConnectCnf(tpam_card *card, struct sk_buff *skb) {
  591. u32 ncoid;
  592. u32 channel;
  593. isdn_ctrl ctrl;
  594. dprintk("TurboPAM(tpam_recv_CConnectCnf): card=%dn", card->id);
  595. /* parse the message contents */
  596. if (parse_CConnectCnf(skb, &ncoid))
  597. return;
  598. /* find the channel by its nco ID */
  599. if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
  600. printk(KERN_ERR "TurboPAM(tpam_recv_CConnectCnf): "
  601.        "ncoid invalid %lun", (unsigned long)ncoid);
  602. return;
  603. }
  604. /* issue a DCONN command to the ISDN link layer if we are in HDLC mode.
  605.  * In modem mode, we alreay did it - the ISDN timer kludge */
  606. if (card->channels[channel].realhdlc) {
  607. ctrl.driver = card->id;
  608. ctrl.command = ISDN_STAT_DCONN;
  609. ctrl.arg = channel;
  610. (* card->interface.statcallb)(&ctrl);
  611. }
  612. }
  613. /*
  614.  * Treat a received CConnectInd message. This function signals a ICALL
  615.  * to the ISDN link layer.
  616.  *
  617.  *  card: the board
  618.  *  skb: the received message
  619.  */
  620. void tpam_recv_CConnectInd(tpam_card *card, struct sk_buff *skb) {
  621. u32 ncoid;
  622. u32 channel;
  623. u8 hdlc, plan, screen;
  624. u8 calling[PHONE_MAXIMUMSIZE], called[PHONE_MAXIMUMSIZE];
  625. isdn_ctrl ctrl;
  626. int status;
  627. dprintk("TurboPAM(tpam_recv_CConnectInd): card=%dn", card->id);
  628. /* parse the message contents */
  629. if (parse_CConnectInd(skb, &ncoid, &hdlc, calling, called, &plan, &screen))
  630. return;
  631. /* find the channel by its nco ID */
  632. if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
  633. printk(KERN_ERR "TurboPAM(tpam_recv_CConnectInd): "
  634.        "ncoid invalid %lun", (unsigned long)ncoid);
  635. return;
  636. }
  637. /* initialize the channel parameters */
  638. card->channels[channel].realhdlc = hdlc;
  639. card->channels[channel].hdlcshift = 0;
  640. card->channels[channel].readytoreceive = 0;
  641. /* issue a ICALL command to the ISDN link layer */
  642. ctrl.driver = card->id;
  643. ctrl.command = ISDN_STAT_ICALL;
  644. ctrl.arg = channel;
  645. memcpy(ctrl.parm.setup.phone, calling, 32);
  646. memcpy(ctrl.parm.setup.eazmsn, called, 32);
  647. ctrl.parm.setup.si1 = 7; /* data capability */
  648. ctrl.parm.setup.si2 = 0;
  649. ctrl.parm.setup.plan = plan;
  650. ctrl.parm.setup.screen = screen;
  651. status = (* card->interface.statcallb)(&ctrl);
  652. switch (status) {
  653. case 1:
  654. case 4:
  655. /* call accepted, link layer will send us a ACCEPTD 
  656.  * command later */
  657. dprintk("TurboPAM(tpam_recv_CConnectInd): "
  658. "card=%d, channel=%d, icall waiting, status=%dn", 
  659. card->id, channel, status);
  660. break;
  661. default:
  662. /* call denied, we build and send a CDisconnectReq */
  663. dprintk("TurboPAM(tpam_recv_CConnectInd): "
  664. "card=%d, channel=%d, icall denied, status=%dn", 
  665. card->id, channel, status);
  666. skb = build_CDisconnectReq(ncoid);
  667. if (!skb)
  668. return;
  669. tpam_enqueue(card, skb);
  670. }
  671. }
  672. /*
  673.  * Treat a received CDisconnectInd message. This function signals a DHUP and
  674.  * a BHUP to the ISDN link layer.
  675.  *
  676.  *  card: the board
  677.  *  skb: the received message
  678.  */
  679. void tpam_recv_CDisconnectInd(tpam_card *card, struct sk_buff *skb) {
  680. u32 ncoid;
  681. u32 channel;
  682. u32 cause;
  683. isdn_ctrl ctrl;
  684. dprintk("TurboPAM(tpam_recv_CDisconnectInd): card=%dn", card->id);
  685. /* parse the message contents */
  686. if (parse_CDisconnectInd(skb, &ncoid, &cause))
  687. return;
  688. /* find the channel by its nco ID */
  689. if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
  690. printk(KERN_ERR "TurboPAM(tpam_recv_CDisconnectInd): "
  691.        "ncoid invalid %lun", (unsigned long)ncoid);
  692. return;
  693. }
  694. /* build and send a CDisconnectRsp */
  695. skb = build_CDisconnectRsp(ncoid);
  696. if (!skb)
  697. return;
  698. tpam_enqueue(card, skb);
  699. /* issue a DHUP to the ISDN link layer */
  700. ctrl.driver = card->id;
  701. ctrl.command = ISDN_STAT_DHUP;
  702. ctrl.arg = channel;
  703. (* card->interface.statcallb)(&ctrl);
  704. /* issue a BHUP to the ISDN link layer */
  705. ctrl.driver = card->id;
  706. ctrl.command = ISDN_STAT_BHUP;
  707. ctrl.arg = channel;
  708. (* card->interface.statcallb)(&ctrl);
  709. }
  710. /*
  711.  * Treat a received CDisconnectCnf message. This function signals a DHUP and
  712.  * a BHUP to the ISDN link layer.
  713.  *
  714.  *  card: the board
  715.  *  skb: the received message
  716.  */
  717. void tpam_recv_CDisconnectCnf(tpam_card *card, struct sk_buff *skb) {
  718. u32 ncoid;
  719. u32 channel;
  720. u32 cause;
  721. isdn_ctrl ctrl;
  722. dprintk("TurboPAM(tpam_recv_CDisconnectCnf): card=%dn", card->id);
  723. /* parse the message contents */
  724. if (parse_CDisconnectCnf(skb, &ncoid, &cause))
  725. return;
  726. /* find the channel by its nco ID */
  727. if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
  728. printk(KERN_ERR "TurboPAM(tpam_recv_CDisconnectCnf): "
  729.        "ncoid invalid %lun", (unsigned long)ncoid);
  730. return;
  731. }
  732. /* issue a DHUP to the ISDN link layer */
  733. ctrl.driver = card->id;
  734. ctrl.command = ISDN_STAT_DHUP;
  735. ctrl.arg = channel;
  736. (* card->interface.statcallb)(&ctrl);
  737. /* issue a BHUP to the ISDN link layer */
  738. ctrl.driver = card->id;
  739. ctrl.command = ISDN_STAT_BHUP;
  740. ctrl.arg = channel;
  741. (* card->interface.statcallb)(&ctrl);
  742. }
  743. /*
  744.  * Treat a received U3DataInd message. This function decodes the data
  745.  * depending on the connection type (modem or HDLC) and passes it to the
  746.  * ISDN link layer by using rcvcallb_skb.
  747.  *
  748.  *  card: the board
  749.  *  skb: the received message + data
  750.  */
  751. void tpam_recv_U3DataInd(tpam_card *card, struct sk_buff *skb) {
  752. u32 ncoid;
  753. u32 channel;
  754. u8 *data;
  755. u16 len;
  756. struct sk_buff *result;
  757. dprintk("TurboPAM(tpam_recv_U3DataInd): card=%d, datalen=%dn", 
  758. card->id, skb->len);
  759. /* parse the message contents */
  760. if (parse_U3DataInd(skb, &ncoid, &data, &len))
  761. return;
  762. /* find the channel by its nco ID */
  763. if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
  764. printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): "
  765.        "ncoid invalid %lun", (unsigned long)ncoid);
  766. return;
  767. }
  768. /* decode the data */
  769. if (card->channels[ncoid].realhdlc) {
  770. /* HDLC mode */
  771. u8 *tempdata;
  772. u32 templen;
  773. if (!(tempdata = (void *)__get_free_page(GFP_ATOMIC))) {
  774. printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): "
  775.        "get_free_page failedn");
  776. return;
  777. }
  778. templen = tpam_hdlc_decode(data, tempdata, len);
  779. templen = hdlc_no_accm_decode(tempdata, templen);
  780. if (!(result = alloc_skb(templen, GFP_ATOMIC))) {
  781. printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): "
  782.        "alloc_skb failedn");
  783. free_page((u32)tempdata);
  784. return;
  785. }
  786. memcpy(skb_put(result, templen), tempdata, templen);
  787. free_page((u32)tempdata);
  788. }
  789. else {
  790. /* modem mode */
  791. if (!(result = alloc_skb(len, GFP_ATOMIC))) {
  792. printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): "
  793.        "alloc_skb failedn");
  794. return;
  795. }
  796. memcpy(skb_put(result, len), data, len);
  797. }
  798. /* In loop mode, resend the data immediatly */
  799. if (card->loopmode) {
  800. struct sk_buff *loopskb;
  801. if (!(loopskb = alloc_skb(skb->len, GFP_ATOMIC))) {
  802. printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): "
  803.        "alloc_skb failedn");
  804. kfree_skb(result);
  805. return;
  806. }
  807. memcpy(skb_put(loopskb, result->len), result->data, 
  808.        result->len);
  809. if (tpam_writebuf_skb(card->id, channel, 0, loopskb) < 0)
  810. kfree_skb(loopskb);
  811. }
  812. /* pass the data to the ISDN link layer */
  813. (* card->interface.rcvcallb_skb)(card->id, channel, result);
  814. }
  815. /*
  816.  * Treat a received U3ReadyToReceiveInd message. This function sets the
  817.  * channel ready flag and triggers the send of data if the channel becomed
  818.  * ready.
  819.  *
  820.  *  card: the board
  821.  *  skb: the received message + data
  822.  */
  823. void tpam_recv_U3ReadyToReceiveInd(tpam_card *card, struct sk_buff *skb) {
  824. u32 ncoid;
  825. u32 channel;
  826. u8 ready;
  827. dprintk("TurboPAM(tpam_recv_U3ReadyToReceiveInd): card=%dn", card->id);
  828. /* parse the message contents */
  829. if (parse_U3ReadyToReceiveInd(skb, &ncoid, &ready))
  830. return;
  831. /* find the channel by its nco ID */
  832. if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
  833. printk(KERN_ERR "TurboPAM(tpam_recv_U3ReadyToReceiveInd): "
  834.        "ncoid invalid %lun", (unsigned long)ncoid);
  835. return;
  836. }
  837. /* set the readytoreceive flag */
  838. card->channels[channel].readytoreceive = ready;
  839. /* if the channel just becomed ready, trigger the send of queued data */
  840. if (ready)
  841. tpam_enqueue_data(&card->channels[channel], NULL);
  842. }
  843. /*
  844.  * Runs the delayed statcallb when its timer expires.
  845.  *
  846.  *  parm: pointer to the tpam_statcallb_data statcallb argument.
  847.  */
  848. static void tpam_statcallb_run(unsigned long parm) {
  849. tpam_statcallb_data *ds = (tpam_statcallb_data *)parm;
  850. dprintk("TurboPAM(tpam_statcallb_run)n");
  851. (* ds->card->interface.statcallb)(&ds->ctrl);
  852. kfree(ds->timer);
  853. kfree(ds);
  854. }
  855. /*
  856.  * Queues a statcallb call for delayed invocation.
  857.  *
  858.  *  card: the board
  859.  *  ctrl: the statcallb argument
  860.  */
  861. static void tpam_statcallb(tpam_card *card, isdn_ctrl ctrl) {
  862. struct timer_list *timer;
  863. tpam_statcallb_data *ds;
  864. dprintk("TurboPAM(tpam_statcallb): card=%dn", card->id);
  865. if (!(timer = (struct timer_list *) kmalloc(sizeof(struct timer_list), 
  866.     GFP_ATOMIC))) {
  867. printk(KERN_ERR "TurboPAM: tpam_statcallb: kmalloc failed!n");
  868. return;
  869. }
  870. if (!(ds = (tpam_statcallb_data *) kmalloc(sizeof(tpam_statcallb_data),
  871.    GFP_ATOMIC))) {
  872. printk(KERN_ERR "TurboPAM: tpam_statcallb: kmalloc failed!n");
  873. kfree(timer);
  874. return;
  875. }
  876. ds->card = card;
  877. ds->timer = timer;
  878. memcpy(&ds->ctrl, &ctrl, sizeof(isdn_ctrl));
  879. init_timer(timer);
  880. timer->function = tpam_statcallb_run;
  881. timer->data = (unsigned long)ds;
  882. timer->expires = jiffies + HZ / 10;   /* 0.1 second */
  883. add_timer(timer);
  884. }