ioctl.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. /*
  2. * Copyright (C) 1996 SpellCaster Telecommunications Inc.
  3. *
  4. * This software may be used and distributed according to the terms
  5. * of the GNU General Public License, incorporated herein by reference.
  6. *
  7. */
  8. #include "includes.h"
  9. #include "hardware.h"
  10. #include "message.h"
  11. #include "card.h"
  12. #include "scioc.h"
  13. static int GetStatus(int card, boardInfo *);
  14. /*
  15. * Process private IOCTL messages (typically from scctrl)
  16. */
  17. int sc_ioctl(int card, scs_ioctl *data)
  18. {
  19. int status;
  20. RspMessage *rcvmsg;
  21. char *spid;
  22. char *dn;
  23. char switchtype;
  24. char speed;
  25. rcvmsg = kmalloc(sizeof(RspMessage), GFP_KERNEL);
  26. if (!rcvmsg)
  27. return -ENOMEM;
  28. switch(data->command) {
  29. case SCIOCRESET: /* Perform a hard reset of the adapter */
  30. {
  31. pr_debug("%s: SCIOCRESET: ioctl received\n",
  32. sc_adapter[card]->devicename);
  33. sc_adapter[card]->StartOnReset = 0;
  34. kfree(rcvmsg);
  35. return reset(card);
  36. }
  37. case SCIOCLOAD:
  38. {
  39. char *srec;
  40. srec = kmalloc(SCIOC_SRECSIZE, GFP_KERNEL);
  41. if (!srec) {
  42. kfree(rcvmsg);
  43. return -ENOMEM;
  44. }
  45. pr_debug("%s: SCIOLOAD: ioctl received\n",
  46. sc_adapter[card]->devicename);
  47. if(sc_adapter[card]->EngineUp) {
  48. pr_debug("%s: SCIOCLOAD: command failed, LoadProc while engine running.\n",
  49. sc_adapter[card]->devicename);
  50. kfree(rcvmsg);
  51. kfree(srec);
  52. return -1;
  53. }
  54. /*
  55. * Get the SRec from user space
  56. */
  57. if (copy_from_user(srec, data->dataptr, SCIOC_SRECSIZE)) {
  58. kfree(rcvmsg);
  59. kfree(srec);
  60. return -EFAULT;
  61. }
  62. status = send_and_receive(card, CMPID, cmReqType2, cmReqClass0, cmReqLoadProc,
  63. 0, SCIOC_SRECSIZE, srec, rcvmsg, SAR_TIMEOUT);
  64. kfree(rcvmsg);
  65. kfree(srec);
  66. if(status) {
  67. pr_debug("%s: SCIOCLOAD: command failed, status = %d\n",
  68. sc_adapter[card]->devicename, status);
  69. return -1;
  70. }
  71. else {
  72. pr_debug("%s: SCIOCLOAD: command successful\n",
  73. sc_adapter[card]->devicename);
  74. return 0;
  75. }
  76. }
  77. case SCIOCSTART:
  78. {
  79. kfree(rcvmsg);
  80. pr_debug("%s: SCIOSTART: ioctl received\n",
  81. sc_adapter[card]->devicename);
  82. if(sc_adapter[card]->EngineUp) {
  83. pr_debug("%s: SCIOCSTART: command failed, engine already running.\n",
  84. sc_adapter[card]->devicename);
  85. return -1;
  86. }
  87. sc_adapter[card]->StartOnReset = 1;
  88. startproc(card);
  89. return 0;
  90. }
  91. case SCIOCSETSWITCH:
  92. {
  93. pr_debug("%s: SCIOSETSWITCH: ioctl received\n",
  94. sc_adapter[card]->devicename);
  95. /*
  96. * Get the switch type from user space
  97. */
  98. if (copy_from_user(&switchtype, data->dataptr, sizeof(char))) {
  99. kfree(rcvmsg);
  100. return -EFAULT;
  101. }
  102. pr_debug("%s: SCIOCSETSWITCH: setting switch type to %d\n",
  103. sc_adapter[card]->devicename,
  104. switchtype);
  105. status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallSetSwitchType,
  106. 0, sizeof(char),&switchtype, rcvmsg, SAR_TIMEOUT);
  107. if(!status && !(rcvmsg->rsp_status)) {
  108. pr_debug("%s: SCIOCSETSWITCH: command successful\n",
  109. sc_adapter[card]->devicename);
  110. kfree(rcvmsg);
  111. return 0;
  112. }
  113. else {
  114. pr_debug("%s: SCIOCSETSWITCH: command failed (status = %d)\n",
  115. sc_adapter[card]->devicename, status);
  116. kfree(rcvmsg);
  117. return status;
  118. }
  119. }
  120. case SCIOCGETSWITCH:
  121. {
  122. pr_debug("%s: SCIOGETSWITCH: ioctl received\n",
  123. sc_adapter[card]->devicename);
  124. /*
  125. * Get the switch type from the board
  126. */
  127. status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
  128. ceReqCallGetSwitchType, 0, 0, NULL, rcvmsg, SAR_TIMEOUT);
  129. if (!status && !(rcvmsg->rsp_status)) {
  130. pr_debug("%s: SCIOCGETSWITCH: command successful\n",
  131. sc_adapter[card]->devicename);
  132. }
  133. else {
  134. pr_debug("%s: SCIOCGETSWITCH: command failed (status = %d)\n",
  135. sc_adapter[card]->devicename, status);
  136. kfree(rcvmsg);
  137. return status;
  138. }
  139. switchtype = rcvmsg->msg_data.byte_array[0];
  140. /*
  141. * Package the switch type and send to user space
  142. */
  143. if (copy_to_user(data->dataptr, &switchtype,
  144. sizeof(char))) {
  145. kfree(rcvmsg);
  146. return -EFAULT;
  147. }
  148. kfree(rcvmsg);
  149. return 0;
  150. }
  151. case SCIOCGETSPID:
  152. {
  153. pr_debug("%s: SCIOGETSPID: ioctl received\n",
  154. sc_adapter[card]->devicename);
  155. spid = kmalloc(SCIOC_SPIDSIZE, GFP_KERNEL);
  156. if (!spid) {
  157. kfree(rcvmsg);
  158. return -ENOMEM;
  159. }
  160. /*
  161. * Get the spid from the board
  162. */
  163. status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetSPID,
  164. data->channel, 0, NULL, rcvmsg, SAR_TIMEOUT);
  165. if (!status) {
  166. pr_debug("%s: SCIOCGETSPID: command successful\n",
  167. sc_adapter[card]->devicename);
  168. } else {
  169. pr_debug("%s: SCIOCGETSPID: command failed (status = %d)\n",
  170. sc_adapter[card]->devicename, status);
  171. kfree(spid);
  172. kfree(rcvmsg);
  173. return status;
  174. }
  175. strcpy(spid, rcvmsg->msg_data.byte_array);
  176. /*
  177. * Package the switch type and send to user space
  178. */
  179. if (copy_to_user(data->dataptr, spid, SCIOC_SPIDSIZE)) {
  180. kfree(spid);
  181. kfree(rcvmsg);
  182. return -EFAULT;
  183. }
  184. kfree(spid);
  185. kfree(rcvmsg);
  186. return 0;
  187. }
  188. case SCIOCSETSPID:
  189. {
  190. pr_debug("%s: DCBIOSETSPID: ioctl received\n",
  191. sc_adapter[card]->devicename);
  192. spid = kmalloc(SCIOC_SPIDSIZE, GFP_KERNEL);
  193. if(!spid) {
  194. kfree(rcvmsg);
  195. return -ENOMEM;
  196. }
  197. /*
  198. * Get the spid from user space
  199. */
  200. if (copy_from_user(spid, data->dataptr, SCIOC_SPIDSIZE)) {
  201. kfree(rcvmsg);
  202. kfree(spid);
  203. return -EFAULT;
  204. }
  205. pr_debug("%s: SCIOCSETSPID: setting channel %d spid to %s\n",
  206. sc_adapter[card]->devicename, data->channel, spid);
  207. status = send_and_receive(card, CEPID, ceReqTypeCall,
  208. ceReqClass0, ceReqCallSetSPID, data->channel,
  209. strlen(spid), spid, rcvmsg, SAR_TIMEOUT);
  210. if(!status && !(rcvmsg->rsp_status)) {
  211. pr_debug("%s: SCIOCSETSPID: command successful\n",
  212. sc_adapter[card]->devicename);
  213. kfree(rcvmsg);
  214. kfree(spid);
  215. return 0;
  216. }
  217. else {
  218. pr_debug("%s: SCIOCSETSPID: command failed (status = %d)\n",
  219. sc_adapter[card]->devicename, status);
  220. kfree(rcvmsg);
  221. kfree(spid);
  222. return status;
  223. }
  224. }
  225. case SCIOCGETDN:
  226. {
  227. pr_debug("%s: SCIOGETDN: ioctl received\n",
  228. sc_adapter[card]->devicename);
  229. /*
  230. * Get the dn from the board
  231. */
  232. status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetMyNumber,
  233. data->channel, 0, NULL, rcvmsg, SAR_TIMEOUT);
  234. if (!status) {
  235. pr_debug("%s: SCIOCGETDN: command successful\n",
  236. sc_adapter[card]->devicename);
  237. }
  238. else {
  239. pr_debug("%s: SCIOCGETDN: command failed (status = %d)\n",
  240. sc_adapter[card]->devicename, status);
  241. kfree(rcvmsg);
  242. return status;
  243. }
  244. dn = kmalloc(SCIOC_DNSIZE, GFP_KERNEL);
  245. if (!dn) {
  246. kfree(rcvmsg);
  247. return -ENOMEM;
  248. }
  249. strcpy(dn, rcvmsg->msg_data.byte_array);
  250. kfree(rcvmsg);
  251. /*
  252. * Package the dn and send to user space
  253. */
  254. if (copy_to_user(data->dataptr, dn, SCIOC_DNSIZE)) {
  255. kfree(dn);
  256. return -EFAULT;
  257. }
  258. kfree(dn);
  259. return 0;
  260. }
  261. case SCIOCSETDN:
  262. {
  263. pr_debug("%s: SCIOSETDN: ioctl received\n",
  264. sc_adapter[card]->devicename);
  265. dn = kmalloc(SCIOC_DNSIZE, GFP_KERNEL);
  266. if (!dn) {
  267. kfree(rcvmsg);
  268. return -ENOMEM;
  269. }
  270. /*
  271. * Get the spid from user space
  272. */
  273. if (copy_from_user(dn, data->dataptr, SCIOC_DNSIZE)) {
  274. kfree(rcvmsg);
  275. kfree(dn);
  276. return -EFAULT;
  277. }
  278. pr_debug("%s: SCIOCSETDN: setting channel %d dn to %s\n",
  279. sc_adapter[card]->devicename, data->channel, dn);
  280. status = send_and_receive(card, CEPID, ceReqTypeCall,
  281. ceReqClass0, ceReqCallSetMyNumber, data->channel,
  282. strlen(dn),dn,rcvmsg, SAR_TIMEOUT);
  283. if(!status && !(rcvmsg->rsp_status)) {
  284. pr_debug("%s: SCIOCSETDN: command successful\n",
  285. sc_adapter[card]->devicename);
  286. kfree(rcvmsg);
  287. kfree(dn);
  288. return 0;
  289. }
  290. else {
  291. pr_debug("%s: SCIOCSETDN: command failed (status = %d)\n",
  292. sc_adapter[card]->devicename, status);
  293. kfree(rcvmsg);
  294. kfree(dn);
  295. return status;
  296. }
  297. }
  298. case SCIOCTRACE:
  299. pr_debug("%s: SCIOTRACE: ioctl received\n",
  300. sc_adapter[card]->devicename);
  301. /* sc_adapter[card]->trace = !sc_adapter[card]->trace;
  302. pr_debug("%s: SCIOCTRACE: tracing turned %s\n",
  303. sc_adapter[card]->devicename,
  304. sc_adapter[card]->trace ? "ON" : "OFF"); */
  305. break;
  306. case SCIOCSTAT:
  307. {
  308. boardInfo *bi;
  309. pr_debug("%s: SCIOSTAT: ioctl received\n",
  310. sc_adapter[card]->devicename);
  311. bi = kmalloc (sizeof(boardInfo), GFP_KERNEL);
  312. if (!bi) {
  313. kfree(rcvmsg);
  314. return -ENOMEM;
  315. }
  316. kfree(rcvmsg);
  317. GetStatus(card, bi);
  318. if (copy_to_user(data->dataptr, bi, sizeof(boardInfo))) {
  319. kfree(bi);
  320. return -EFAULT;
  321. }
  322. kfree(bi);
  323. return 0;
  324. }
  325. case SCIOCGETSPEED:
  326. {
  327. pr_debug("%s: SCIOGETSPEED: ioctl received\n",
  328. sc_adapter[card]->devicename);
  329. /*
  330. * Get the speed from the board
  331. */
  332. status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
  333. ceReqCallGetCallType, data->channel, 0, NULL, rcvmsg, SAR_TIMEOUT);
  334. if (!status && !(rcvmsg->rsp_status)) {
  335. pr_debug("%s: SCIOCGETSPEED: command successful\n",
  336. sc_adapter[card]->devicename);
  337. }
  338. else {
  339. pr_debug("%s: SCIOCGETSPEED: command failed (status = %d)\n",
  340. sc_adapter[card]->devicename, status);
  341. kfree(rcvmsg);
  342. return status;
  343. }
  344. speed = rcvmsg->msg_data.byte_array[0];
  345. kfree(rcvmsg);
  346. /*
  347. * Package the switch type and send to user space
  348. */
  349. if (copy_to_user(data->dataptr, &speed, sizeof(char)))
  350. return -EFAULT;
  351. return 0;
  352. }
  353. case SCIOCSETSPEED:
  354. pr_debug("%s: SCIOCSETSPEED: ioctl received\n",
  355. sc_adapter[card]->devicename);
  356. break;
  357. case SCIOCLOOPTST:
  358. pr_debug("%s: SCIOCLOOPTST: ioctl received\n",
  359. sc_adapter[card]->devicename);
  360. break;
  361. default:
  362. kfree(rcvmsg);
  363. return -1;
  364. }
  365. kfree(rcvmsg);
  366. return 0;
  367. }
  368. static int GetStatus(int card, boardInfo *bi)
  369. {
  370. RspMessage rcvmsg;
  371. int i, status;
  372. /*
  373. * Fill in some of the basic info about the board
  374. */
  375. bi->modelid = sc_adapter[card]->model;
  376. strcpy(bi->serial_no, sc_adapter[card]->hwconfig.serial_no);
  377. strcpy(bi->part_no, sc_adapter[card]->hwconfig.part_no);
  378. bi->iobase = sc_adapter[card]->iobase;
  379. bi->rambase = sc_adapter[card]->rambase;
  380. bi->irq = sc_adapter[card]->interrupt;
  381. bi->ramsize = sc_adapter[card]->hwconfig.ram_size;
  382. bi->interface = sc_adapter[card]->hwconfig.st_u_sense;
  383. strcpy(bi->load_ver, sc_adapter[card]->load_ver);
  384. strcpy(bi->proc_ver, sc_adapter[card]->proc_ver);
  385. /*
  386. * Get the current PhyStats and LnkStats
  387. */
  388. status = send_and_receive(card, CEPID, ceReqTypePhy, ceReqClass2,
  389. ceReqPhyStatus, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
  390. if(!status) {
  391. if(sc_adapter[card]->model < PRI_BOARD) {
  392. bi->l1_status = rcvmsg.msg_data.byte_array[2];
  393. for(i = 0 ; i < BRI_CHANNELS ; i++)
  394. bi->status.bristats[i].phy_stat =
  395. rcvmsg.msg_data.byte_array[i];
  396. }
  397. else {
  398. bi->l1_status = rcvmsg.msg_data.byte_array[0];
  399. bi->l2_status = rcvmsg.msg_data.byte_array[1];
  400. for(i = 0 ; i < PRI_CHANNELS ; i++)
  401. bi->status.pristats[i].phy_stat =
  402. rcvmsg.msg_data.byte_array[i+2];
  403. }
  404. }
  405. /*
  406. * Get the call types for each channel
  407. */
  408. for (i = 0 ; i < sc_adapter[card]->nChannels ; i++) {
  409. status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
  410. ceReqCallGetCallType, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
  411. if(!status) {
  412. if (sc_adapter[card]->model == PRI_BOARD) {
  413. bi->status.pristats[i].call_type =
  414. rcvmsg.msg_data.byte_array[0];
  415. }
  416. else {
  417. bi->status.bristats[i].call_type =
  418. rcvmsg.msg_data.byte_array[0];
  419. }
  420. }
  421. }
  422. /*
  423. * If PRI, get the call states and service states for each channel
  424. */
  425. if (sc_adapter[card]->model == PRI_BOARD) {
  426. /*
  427. * Get the call states
  428. */
  429. status = send_and_receive(card, CEPID, ceReqTypeStat, ceReqClass2,
  430. ceReqPhyChCallState, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
  431. if(!status) {
  432. for( i = 0 ; i < PRI_CHANNELS ; i++ )
  433. bi->status.pristats[i].call_state =
  434. rcvmsg.msg_data.byte_array[i];
  435. }
  436. /*
  437. * Get the service states
  438. */
  439. status = send_and_receive(card, CEPID, ceReqTypeStat, ceReqClass2,
  440. ceReqPhyChServState, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
  441. if(!status) {
  442. for( i = 0 ; i < PRI_CHANNELS ; i++ )
  443. bi->status.pristats[i].serv_state =
  444. rcvmsg.msg_data.byte_array[i];
  445. }
  446. /*
  447. * Get the link stats for the channels
  448. */
  449. for (i = 1 ; i <= PRI_CHANNELS ; i++) {
  450. status = send_and_receive(card, CEPID, ceReqTypeLnk, ceReqClass0,
  451. ceReqLnkGetStats, i, 0, NULL, &rcvmsg, SAR_TIMEOUT);
  452. if (!status) {
  453. bi->status.pristats[i-1].link_stats.tx_good =
  454. (unsigned long)rcvmsg.msg_data.byte_array[0];
  455. bi->status.pristats[i-1].link_stats.tx_bad =
  456. (unsigned long)rcvmsg.msg_data.byte_array[4];
  457. bi->status.pristats[i-1].link_stats.rx_good =
  458. (unsigned long)rcvmsg.msg_data.byte_array[8];
  459. bi->status.pristats[i-1].link_stats.rx_bad =
  460. (unsigned long)rcvmsg.msg_data.byte_array[12];
  461. }
  462. }
  463. /*
  464. * Link stats for the D channel
  465. */
  466. status = send_and_receive(card, CEPID, ceReqTypeLnk, ceReqClass0,
  467. ceReqLnkGetStats, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
  468. if (!status) {
  469. bi->dch_stats.tx_good = (unsigned long)rcvmsg.msg_data.byte_array[0];
  470. bi->dch_stats.tx_bad = (unsigned long)rcvmsg.msg_data.byte_array[4];
  471. bi->dch_stats.rx_good = (unsigned long)rcvmsg.msg_data.byte_array[8];
  472. bi->dch_stats.rx_bad = (unsigned long)rcvmsg.msg_data.byte_array[12];
  473. }
  474. return 0;
  475. }
  476. /*
  477. * If BRI or POTS, Get SPID, DN and call types for each channel
  478. */
  479. /*
  480. * Get the link stats for the channels
  481. */
  482. status = send_and_receive(card, CEPID, ceReqTypeLnk, ceReqClass0,
  483. ceReqLnkGetStats, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
  484. if (!status) {
  485. bi->dch_stats.tx_good = (unsigned long)rcvmsg.msg_data.byte_array[0];
  486. bi->dch_stats.tx_bad = (unsigned long)rcvmsg.msg_data.byte_array[4];
  487. bi->dch_stats.rx_good = (unsigned long)rcvmsg.msg_data.byte_array[8];
  488. bi->dch_stats.rx_bad = (unsigned long)rcvmsg.msg_data.byte_array[12];
  489. bi->status.bristats[0].link_stats.tx_good =
  490. (unsigned long)rcvmsg.msg_data.byte_array[16];
  491. bi->status.bristats[0].link_stats.tx_bad =
  492. (unsigned long)rcvmsg.msg_data.byte_array[20];
  493. bi->status.bristats[0].link_stats.rx_good =
  494. (unsigned long)rcvmsg.msg_data.byte_array[24];
  495. bi->status.bristats[0].link_stats.rx_bad =
  496. (unsigned long)rcvmsg.msg_data.byte_array[28];
  497. bi->status.bristats[1].link_stats.tx_good =
  498. (unsigned long)rcvmsg.msg_data.byte_array[32];
  499. bi->status.bristats[1].link_stats.tx_bad =
  500. (unsigned long)rcvmsg.msg_data.byte_array[36];
  501. bi->status.bristats[1].link_stats.rx_good =
  502. (unsigned long)rcvmsg.msg_data.byte_array[40];
  503. bi->status.bristats[1].link_stats.rx_bad =
  504. (unsigned long)rcvmsg.msg_data.byte_array[44];
  505. }
  506. /*
  507. * Get the SPIDs
  508. */
  509. for (i = 0 ; i < BRI_CHANNELS ; i++) {
  510. status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
  511. ceReqCallGetSPID, i+1, 0, NULL, &rcvmsg, SAR_TIMEOUT);
  512. if (!status)
  513. strcpy(bi->status.bristats[i].spid, rcvmsg.msg_data.byte_array);
  514. }
  515. /*
  516. * Get the DNs
  517. */
  518. for (i = 0 ; i < BRI_CHANNELS ; i++) {
  519. status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
  520. ceReqCallGetMyNumber, i+1, 0, NULL, &rcvmsg, SAR_TIMEOUT);
  521. if (!status)
  522. strcpy(bi->status.bristats[i].dn, rcvmsg.msg_data.byte_array);
  523. }
  524. return 0;
  525. }