ioctl.c 15 KB

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