ioctl.c 15 KB

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