ioctl.c 15 KB

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