ioctl.c 15 KB

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