ioctl.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  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 = kzalloc(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. strlcpy(spid, rcvmsg->msg_data.byte_array, SCIOC_SPIDSIZE);
  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. /*
  193. * Get the spid from user space
  194. */
  195. spid = memdup_user(data->dataptr, SCIOC_SPIDSIZE);
  196. if (IS_ERR(spid)) {
  197. kfree(rcvmsg);
  198. return PTR_ERR(spid);
  199. }
  200. pr_debug("%s: SCIOCSETSPID: setting channel %d spid to %s\n",
  201. sc_adapter[card]->devicename, data->channel, spid);
  202. status = send_and_receive(card, CEPID, ceReqTypeCall,
  203. ceReqClass0, ceReqCallSetSPID, data->channel,
  204. strlen(spid), spid, rcvmsg, SAR_TIMEOUT);
  205. if (!status && !(rcvmsg->rsp_status)) {
  206. pr_debug("%s: SCIOCSETSPID: command successful\n",
  207. sc_adapter[card]->devicename);
  208. kfree(rcvmsg);
  209. kfree(spid);
  210. return 0;
  211. }
  212. else {
  213. pr_debug("%s: SCIOCSETSPID: command failed (status = %d)\n",
  214. sc_adapter[card]->devicename, status);
  215. kfree(rcvmsg);
  216. kfree(spid);
  217. return status;
  218. }
  219. }
  220. case SCIOCGETDN:
  221. {
  222. pr_debug("%s: SCIOGETDN: ioctl received\n",
  223. sc_adapter[card]->devicename);
  224. /*
  225. * Get the dn from the board
  226. */
  227. status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetMyNumber,
  228. data->channel, 0, NULL, rcvmsg, SAR_TIMEOUT);
  229. if (!status) {
  230. pr_debug("%s: SCIOCGETDN: command successful\n",
  231. sc_adapter[card]->devicename);
  232. }
  233. else {
  234. pr_debug("%s: SCIOCGETDN: command failed (status = %d)\n",
  235. sc_adapter[card]->devicename, status);
  236. kfree(rcvmsg);
  237. return status;
  238. }
  239. dn = kzalloc(SCIOC_DNSIZE, GFP_KERNEL);
  240. if (!dn) {
  241. kfree(rcvmsg);
  242. return -ENOMEM;
  243. }
  244. strlcpy(dn, rcvmsg->msg_data.byte_array, SCIOC_DNSIZE);
  245. kfree(rcvmsg);
  246. /*
  247. * Package the dn and send to user space
  248. */
  249. if (copy_to_user(data->dataptr, dn, SCIOC_DNSIZE)) {
  250. kfree(dn);
  251. return -EFAULT;
  252. }
  253. kfree(dn);
  254. return 0;
  255. }
  256. case SCIOCSETDN:
  257. {
  258. pr_debug("%s: SCIOSETDN: ioctl received\n",
  259. sc_adapter[card]->devicename);
  260. /*
  261. * Get the spid from user space
  262. */
  263. dn = memdup_user(data->dataptr, SCIOC_DNSIZE);
  264. if (IS_ERR(dn)) {
  265. kfree(rcvmsg);
  266. return PTR_ERR(dn);
  267. }
  268. pr_debug("%s: SCIOCSETDN: setting channel %d dn to %s\n",
  269. sc_adapter[card]->devicename, data->channel, dn);
  270. status = send_and_receive(card, CEPID, ceReqTypeCall,
  271. ceReqClass0, ceReqCallSetMyNumber, data->channel,
  272. strlen(dn), dn, rcvmsg, SAR_TIMEOUT);
  273. if (!status && !(rcvmsg->rsp_status)) {
  274. pr_debug("%s: SCIOCSETDN: command successful\n",
  275. sc_adapter[card]->devicename);
  276. kfree(rcvmsg);
  277. kfree(dn);
  278. return 0;
  279. }
  280. else {
  281. pr_debug("%s: SCIOCSETDN: command failed (status = %d)\n",
  282. sc_adapter[card]->devicename, status);
  283. kfree(rcvmsg);
  284. kfree(dn);
  285. return status;
  286. }
  287. }
  288. case SCIOCTRACE:
  289. pr_debug("%s: SCIOTRACE: ioctl received\n",
  290. sc_adapter[card]->devicename);
  291. /* sc_adapter[card]->trace = !sc_adapter[card]->trace;
  292. pr_debug("%s: SCIOCTRACE: tracing turned %s\n",
  293. sc_adapter[card]->devicename,
  294. sc_adapter[card]->trace ? "ON" : "OFF"); */
  295. break;
  296. case SCIOCSTAT:
  297. {
  298. boardInfo *bi;
  299. pr_debug("%s: SCIOSTAT: ioctl received\n",
  300. sc_adapter[card]->devicename);
  301. bi = kzalloc(sizeof(boardInfo), GFP_KERNEL);
  302. if (!bi) {
  303. kfree(rcvmsg);
  304. return -ENOMEM;
  305. }
  306. kfree(rcvmsg);
  307. GetStatus(card, bi);
  308. if (copy_to_user(data->dataptr, bi, sizeof(boardInfo))) {
  309. kfree(bi);
  310. return -EFAULT;
  311. }
  312. kfree(bi);
  313. return 0;
  314. }
  315. case SCIOCGETSPEED:
  316. {
  317. pr_debug("%s: SCIOGETSPEED: ioctl received\n",
  318. sc_adapter[card]->devicename);
  319. /*
  320. * Get the speed from the board
  321. */
  322. status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
  323. ceReqCallGetCallType, data->channel, 0, NULL, rcvmsg, SAR_TIMEOUT);
  324. if (!status && !(rcvmsg->rsp_status)) {
  325. pr_debug("%s: SCIOCGETSPEED: command successful\n",
  326. sc_adapter[card]->devicename);
  327. }
  328. else {
  329. pr_debug("%s: SCIOCGETSPEED: command failed (status = %d)\n",
  330. sc_adapter[card]->devicename, status);
  331. kfree(rcvmsg);
  332. return status;
  333. }
  334. speed = rcvmsg->msg_data.byte_array[0];
  335. kfree(rcvmsg);
  336. /*
  337. * Package the switch type and send to user space
  338. */
  339. if (copy_to_user(data->dataptr, &speed, sizeof(char)))
  340. return -EFAULT;
  341. return 0;
  342. }
  343. case SCIOCSETSPEED:
  344. pr_debug("%s: SCIOCSETSPEED: ioctl received\n",
  345. sc_adapter[card]->devicename);
  346. break;
  347. case SCIOCLOOPTST:
  348. pr_debug("%s: SCIOCLOOPTST: ioctl received\n",
  349. sc_adapter[card]->devicename);
  350. break;
  351. default:
  352. kfree(rcvmsg);
  353. return -1;
  354. }
  355. kfree(rcvmsg);
  356. return 0;
  357. }
  358. static int GetStatus(int card, boardInfo *bi)
  359. {
  360. RspMessage rcvmsg;
  361. int i, status;
  362. /*
  363. * Fill in some of the basic info about the board
  364. */
  365. bi->modelid = sc_adapter[card]->model;
  366. strcpy(bi->serial_no, sc_adapter[card]->hwconfig.serial_no);
  367. strcpy(bi->part_no, sc_adapter[card]->hwconfig.part_no);
  368. bi->iobase = sc_adapter[card]->iobase;
  369. bi->rambase = sc_adapter[card]->rambase;
  370. bi->irq = sc_adapter[card]->interrupt;
  371. bi->ramsize = sc_adapter[card]->hwconfig.ram_size;
  372. bi->interface = sc_adapter[card]->hwconfig.st_u_sense;
  373. strcpy(bi->load_ver, sc_adapter[card]->load_ver);
  374. strcpy(bi->proc_ver, sc_adapter[card]->proc_ver);
  375. /*
  376. * Get the current PhyStats and LnkStats
  377. */
  378. status = send_and_receive(card, CEPID, ceReqTypePhy, ceReqClass2,
  379. ceReqPhyStatus, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
  380. if (!status) {
  381. if (sc_adapter[card]->model < PRI_BOARD) {
  382. bi->l1_status = rcvmsg.msg_data.byte_array[2];
  383. for (i = 0; i < BRI_CHANNELS; i++)
  384. bi->status.bristats[i].phy_stat =
  385. rcvmsg.msg_data.byte_array[i];
  386. }
  387. else {
  388. bi->l1_status = rcvmsg.msg_data.byte_array[0];
  389. bi->l2_status = rcvmsg.msg_data.byte_array[1];
  390. for (i = 0; i < PRI_CHANNELS; i++)
  391. bi->status.pristats[i].phy_stat =
  392. rcvmsg.msg_data.byte_array[i + 2];
  393. }
  394. }
  395. /*
  396. * Get the call types for each channel
  397. */
  398. for (i = 0; i < sc_adapter[card]->nChannels; i++) {
  399. status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
  400. ceReqCallGetCallType, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
  401. if (!status) {
  402. if (sc_adapter[card]->model == PRI_BOARD) {
  403. bi->status.pristats[i].call_type =
  404. rcvmsg.msg_data.byte_array[0];
  405. }
  406. else {
  407. bi->status.bristats[i].call_type =
  408. rcvmsg.msg_data.byte_array[0];
  409. }
  410. }
  411. }
  412. /*
  413. * If PRI, get the call states and service states for each channel
  414. */
  415. if (sc_adapter[card]->model == PRI_BOARD) {
  416. /*
  417. * Get the call states
  418. */
  419. status = send_and_receive(card, CEPID, ceReqTypeStat, ceReqClass2,
  420. ceReqPhyChCallState, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
  421. if (!status) {
  422. for (i = 0; i < PRI_CHANNELS; i++)
  423. bi->status.pristats[i].call_state =
  424. rcvmsg.msg_data.byte_array[i];
  425. }
  426. /*
  427. * Get the service states
  428. */
  429. status = send_and_receive(card, CEPID, ceReqTypeStat, ceReqClass2,
  430. ceReqPhyChServState, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
  431. if (!status) {
  432. for (i = 0; i < PRI_CHANNELS; i++)
  433. bi->status.pristats[i].serv_state =
  434. rcvmsg.msg_data.byte_array[i];
  435. }
  436. /*
  437. * Get the link stats for the channels
  438. */
  439. for (i = 1; i <= PRI_CHANNELS; i++) {
  440. status = send_and_receive(card, CEPID, ceReqTypeLnk, ceReqClass0,
  441. ceReqLnkGetStats, i, 0, NULL, &rcvmsg, SAR_TIMEOUT);
  442. if (!status) {
  443. bi->status.pristats[i - 1].link_stats.tx_good =
  444. (unsigned long)rcvmsg.msg_data.byte_array[0];
  445. bi->status.pristats[i - 1].link_stats.tx_bad =
  446. (unsigned long)rcvmsg.msg_data.byte_array[4];
  447. bi->status.pristats[i - 1].link_stats.rx_good =
  448. (unsigned long)rcvmsg.msg_data.byte_array[8];
  449. bi->status.pristats[i - 1].link_stats.rx_bad =
  450. (unsigned long)rcvmsg.msg_data.byte_array[12];
  451. }
  452. }
  453. /*
  454. * Link stats for the D channel
  455. */
  456. status = send_and_receive(card, CEPID, ceReqTypeLnk, ceReqClass0,
  457. ceReqLnkGetStats, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
  458. if (!status) {
  459. bi->dch_stats.tx_good = (unsigned long)rcvmsg.msg_data.byte_array[0];
  460. bi->dch_stats.tx_bad = (unsigned long)rcvmsg.msg_data.byte_array[4];
  461. bi->dch_stats.rx_good = (unsigned long)rcvmsg.msg_data.byte_array[8];
  462. bi->dch_stats.rx_bad = (unsigned long)rcvmsg.msg_data.byte_array[12];
  463. }
  464. return 0;
  465. }
  466. /*
  467. * If BRI or POTS, Get SPID, DN and call types for each channel
  468. */
  469. /*
  470. * Get the link stats for the channels
  471. */
  472. status = send_and_receive(card, CEPID, ceReqTypeLnk, ceReqClass0,
  473. ceReqLnkGetStats, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
  474. if (!status) {
  475. bi->dch_stats.tx_good = (unsigned long)rcvmsg.msg_data.byte_array[0];
  476. bi->dch_stats.tx_bad = (unsigned long)rcvmsg.msg_data.byte_array[4];
  477. bi->dch_stats.rx_good = (unsigned long)rcvmsg.msg_data.byte_array[8];
  478. bi->dch_stats.rx_bad = (unsigned long)rcvmsg.msg_data.byte_array[12];
  479. bi->status.bristats[0].link_stats.tx_good =
  480. (unsigned long)rcvmsg.msg_data.byte_array[16];
  481. bi->status.bristats[0].link_stats.tx_bad =
  482. (unsigned long)rcvmsg.msg_data.byte_array[20];
  483. bi->status.bristats[0].link_stats.rx_good =
  484. (unsigned long)rcvmsg.msg_data.byte_array[24];
  485. bi->status.bristats[0].link_stats.rx_bad =
  486. (unsigned long)rcvmsg.msg_data.byte_array[28];
  487. bi->status.bristats[1].link_stats.tx_good =
  488. (unsigned long)rcvmsg.msg_data.byte_array[32];
  489. bi->status.bristats[1].link_stats.tx_bad =
  490. (unsigned long)rcvmsg.msg_data.byte_array[36];
  491. bi->status.bristats[1].link_stats.rx_good =
  492. (unsigned long)rcvmsg.msg_data.byte_array[40];
  493. bi->status.bristats[1].link_stats.rx_bad =
  494. (unsigned long)rcvmsg.msg_data.byte_array[44];
  495. }
  496. /*
  497. * Get the SPIDs
  498. */
  499. for (i = 0; i < BRI_CHANNELS; i++) {
  500. status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
  501. ceReqCallGetSPID, i + 1, 0, NULL, &rcvmsg, SAR_TIMEOUT);
  502. if (!status)
  503. strcpy(bi->status.bristats[i].spid, rcvmsg.msg_data.byte_array);
  504. }
  505. /*
  506. * Get the DNs
  507. */
  508. for (i = 0; i < BRI_CHANNELS; i++) {
  509. status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
  510. ceReqCallGetMyNumber, i + 1, 0, NULL, &rcvmsg, SAR_TIMEOUT);
  511. if (!status)
  512. strcpy(bi->status.bristats[i].dn, rcvmsg.msg_data.byte_array);
  513. }
  514. return 0;
  515. }