mISDNipac.c 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * isac.c ISAC specific routines
  4. *
  5. * Author Karsten Keil <[email protected]>
  6. *
  7. * Copyright 2009 by Karsten Keil <[email protected]>
  8. */
  9. #include <linux/irqreturn.h>
  10. #include <linux/slab.h>
  11. #include <linux/module.h>
  12. #include <linux/mISDNhw.h>
  13. #include "ipac.h"
  14. #define DBUSY_TIMER_VALUE 80
  15. #define ARCOFI_USE 1
  16. #define ISAC_REV "2.0"
  17. MODULE_AUTHOR("Karsten Keil");
  18. MODULE_VERSION(ISAC_REV);
  19. MODULE_LICENSE("GPL v2");
  20. #define ReadISAC(is, o) (is->read_reg(is->dch.hw, o + is->off))
  21. #define WriteISAC(is, o, v) (is->write_reg(is->dch.hw, o + is->off, v))
  22. #define ReadHSCX(h, o) (h->ip->read_reg(h->ip->hw, h->off + o))
  23. #define WriteHSCX(h, o, v) (h->ip->write_reg(h->ip->hw, h->off + o, v))
  24. #define ReadIPAC(ip, o) (ip->read_reg(ip->hw, o))
  25. #define WriteIPAC(ip, o, v) (ip->write_reg(ip->hw, o, v))
  26. static inline void
  27. ph_command(struct isac_hw *isac, u8 command)
  28. {
  29. pr_debug("%s: ph_command %x\n", isac->name, command);
  30. if (isac->type & IPAC_TYPE_ISACX)
  31. WriteISAC(isac, ISACX_CIX0, (command << 4) | 0xE);
  32. else
  33. WriteISAC(isac, ISAC_CIX0, (command << 2) | 3);
  34. }
  35. static void
  36. isac_ph_state_change(struct isac_hw *isac)
  37. {
  38. switch (isac->state) {
  39. case (ISAC_IND_RS):
  40. case (ISAC_IND_EI):
  41. ph_command(isac, ISAC_CMD_DUI);
  42. }
  43. schedule_event(&isac->dch, FLG_PHCHANGE);
  44. }
  45. static void
  46. isac_ph_state_bh(struct dchannel *dch)
  47. {
  48. struct isac_hw *isac = container_of(dch, struct isac_hw, dch);
  49. switch (isac->state) {
  50. case ISAC_IND_RS:
  51. case ISAC_IND_EI:
  52. dch->state = 0;
  53. l1_event(dch->l1, HW_RESET_IND);
  54. break;
  55. case ISAC_IND_DID:
  56. dch->state = 3;
  57. l1_event(dch->l1, HW_DEACT_CNF);
  58. break;
  59. case ISAC_IND_DR:
  60. case ISAC_IND_DR6:
  61. dch->state = 3;
  62. l1_event(dch->l1, HW_DEACT_IND);
  63. break;
  64. case ISAC_IND_PU:
  65. dch->state = 4;
  66. l1_event(dch->l1, HW_POWERUP_IND);
  67. break;
  68. case ISAC_IND_RSY:
  69. if (dch->state <= 5) {
  70. dch->state = 5;
  71. l1_event(dch->l1, ANYSIGNAL);
  72. } else {
  73. dch->state = 8;
  74. l1_event(dch->l1, LOSTFRAMING);
  75. }
  76. break;
  77. case ISAC_IND_ARD:
  78. dch->state = 6;
  79. l1_event(dch->l1, INFO2);
  80. break;
  81. case ISAC_IND_AI8:
  82. dch->state = 7;
  83. l1_event(dch->l1, INFO4_P8);
  84. break;
  85. case ISAC_IND_AI10:
  86. dch->state = 7;
  87. l1_event(dch->l1, INFO4_P10);
  88. break;
  89. }
  90. pr_debug("%s: TE newstate %x\n", isac->name, dch->state);
  91. }
  92. static void
  93. isac_empty_fifo(struct isac_hw *isac, int count)
  94. {
  95. u8 *ptr;
  96. pr_debug("%s: %s %d\n", isac->name, __func__, count);
  97. if (!isac->dch.rx_skb) {
  98. isac->dch.rx_skb = mI_alloc_skb(isac->dch.maxlen, GFP_ATOMIC);
  99. if (!isac->dch.rx_skb) {
  100. pr_info("%s: D receive out of memory\n", isac->name);
  101. WriteISAC(isac, ISAC_CMDR, 0x80);
  102. return;
  103. }
  104. }
  105. if ((isac->dch.rx_skb->len + count) >= isac->dch.maxlen) {
  106. pr_debug("%s: %s overrun %d\n", isac->name, __func__,
  107. isac->dch.rx_skb->len + count);
  108. WriteISAC(isac, ISAC_CMDR, 0x80);
  109. return;
  110. }
  111. ptr = skb_put(isac->dch.rx_skb, count);
  112. isac->read_fifo(isac->dch.hw, isac->off, ptr, count);
  113. WriteISAC(isac, ISAC_CMDR, 0x80);
  114. if (isac->dch.debug & DEBUG_HW_DFIFO) {
  115. char pfx[MISDN_MAX_IDLEN + 16];
  116. snprintf(pfx, MISDN_MAX_IDLEN + 15, "D-recv %s %d ",
  117. isac->name, count);
  118. print_hex_dump_bytes(pfx, DUMP_PREFIX_OFFSET, ptr, count);
  119. }
  120. }
  121. static void
  122. isac_fill_fifo(struct isac_hw *isac)
  123. {
  124. int count, more;
  125. u8 *ptr;
  126. if (!isac->dch.tx_skb)
  127. return;
  128. count = isac->dch.tx_skb->len - isac->dch.tx_idx;
  129. if (count <= 0)
  130. return;
  131. more = 0;
  132. if (count > 32) {
  133. more = !0;
  134. count = 32;
  135. }
  136. pr_debug("%s: %s %d\n", isac->name, __func__, count);
  137. ptr = isac->dch.tx_skb->data + isac->dch.tx_idx;
  138. isac->dch.tx_idx += count;
  139. isac->write_fifo(isac->dch.hw, isac->off, ptr, count);
  140. WriteISAC(isac, ISAC_CMDR, more ? 0x8 : 0xa);
  141. if (test_and_set_bit(FLG_BUSY_TIMER, &isac->dch.Flags)) {
  142. pr_debug("%s: %s dbusytimer running\n", isac->name, __func__);
  143. del_timer(&isac->dch.timer);
  144. }
  145. isac->dch.timer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
  146. add_timer(&isac->dch.timer);
  147. if (isac->dch.debug & DEBUG_HW_DFIFO) {
  148. char pfx[MISDN_MAX_IDLEN + 16];
  149. snprintf(pfx, MISDN_MAX_IDLEN + 15, "D-send %s %d ",
  150. isac->name, count);
  151. print_hex_dump_bytes(pfx, DUMP_PREFIX_OFFSET, ptr, count);
  152. }
  153. }
  154. static void
  155. isac_rme_irq(struct isac_hw *isac)
  156. {
  157. u8 val, count;
  158. val = ReadISAC(isac, ISAC_RSTA);
  159. if ((val & 0x70) != 0x20) {
  160. if (val & 0x40) {
  161. pr_debug("%s: ISAC RDO\n", isac->name);
  162. #ifdef ERROR_STATISTIC
  163. isac->dch.err_rx++;
  164. #endif
  165. }
  166. if (!(val & 0x20)) {
  167. pr_debug("%s: ISAC CRC error\n", isac->name);
  168. #ifdef ERROR_STATISTIC
  169. isac->dch.err_crc++;
  170. #endif
  171. }
  172. WriteISAC(isac, ISAC_CMDR, 0x80);
  173. dev_kfree_skb(isac->dch.rx_skb);
  174. isac->dch.rx_skb = NULL;
  175. } else {
  176. count = ReadISAC(isac, ISAC_RBCL) & 0x1f;
  177. if (count == 0)
  178. count = 32;
  179. isac_empty_fifo(isac, count);
  180. recv_Dchannel(&isac->dch);
  181. }
  182. }
  183. static void
  184. isac_xpr_irq(struct isac_hw *isac)
  185. {
  186. if (test_and_clear_bit(FLG_BUSY_TIMER, &isac->dch.Flags))
  187. del_timer(&isac->dch.timer);
  188. if (isac->dch.tx_skb && isac->dch.tx_idx < isac->dch.tx_skb->len) {
  189. isac_fill_fifo(isac);
  190. } else {
  191. dev_kfree_skb(isac->dch.tx_skb);
  192. if (get_next_dframe(&isac->dch))
  193. isac_fill_fifo(isac);
  194. }
  195. }
  196. static void
  197. isac_retransmit(struct isac_hw *isac)
  198. {
  199. if (test_and_clear_bit(FLG_BUSY_TIMER, &isac->dch.Flags))
  200. del_timer(&isac->dch.timer);
  201. if (test_bit(FLG_TX_BUSY, &isac->dch.Flags)) {
  202. /* Restart frame */
  203. isac->dch.tx_idx = 0;
  204. isac_fill_fifo(isac);
  205. } else if (isac->dch.tx_skb) { /* should not happen */
  206. pr_info("%s: tx_skb exist but not busy\n", isac->name);
  207. test_and_set_bit(FLG_TX_BUSY, &isac->dch.Flags);
  208. isac->dch.tx_idx = 0;
  209. isac_fill_fifo(isac);
  210. } else {
  211. pr_info("%s: ISAC XDU no TX_BUSY\n", isac->name);
  212. if (get_next_dframe(&isac->dch))
  213. isac_fill_fifo(isac);
  214. }
  215. }
  216. static void
  217. isac_mos_irq(struct isac_hw *isac)
  218. {
  219. u8 val;
  220. int ret;
  221. val = ReadISAC(isac, ISAC_MOSR);
  222. pr_debug("%s: ISAC MOSR %02x\n", isac->name, val);
  223. #if ARCOFI_USE
  224. if (val & 0x08) {
  225. if (!isac->mon_rx) {
  226. isac->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC);
  227. if (!isac->mon_rx) {
  228. pr_info("%s: ISAC MON RX out of memory!\n",
  229. isac->name);
  230. isac->mocr &= 0xf0;
  231. isac->mocr |= 0x0a;
  232. WriteISAC(isac, ISAC_MOCR, isac->mocr);
  233. goto afterMONR0;
  234. } else
  235. isac->mon_rxp = 0;
  236. }
  237. if (isac->mon_rxp >= MAX_MON_FRAME) {
  238. isac->mocr &= 0xf0;
  239. isac->mocr |= 0x0a;
  240. WriteISAC(isac, ISAC_MOCR, isac->mocr);
  241. isac->mon_rxp = 0;
  242. pr_debug("%s: ISAC MON RX overflow!\n", isac->name);
  243. goto afterMONR0;
  244. }
  245. isac->mon_rx[isac->mon_rxp++] = ReadISAC(isac, ISAC_MOR0);
  246. pr_debug("%s: ISAC MOR0 %02x\n", isac->name,
  247. isac->mon_rx[isac->mon_rxp - 1]);
  248. if (isac->mon_rxp == 1) {
  249. isac->mocr |= 0x04;
  250. WriteISAC(isac, ISAC_MOCR, isac->mocr);
  251. }
  252. }
  253. afterMONR0:
  254. if (val & 0x80) {
  255. if (!isac->mon_rx) {
  256. isac->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC);
  257. if (!isac->mon_rx) {
  258. pr_info("%s: ISAC MON RX out of memory!\n",
  259. isac->name);
  260. isac->mocr &= 0x0f;
  261. isac->mocr |= 0xa0;
  262. WriteISAC(isac, ISAC_MOCR, isac->mocr);
  263. goto afterMONR1;
  264. } else
  265. isac->mon_rxp = 0;
  266. }
  267. if (isac->mon_rxp >= MAX_MON_FRAME) {
  268. isac->mocr &= 0x0f;
  269. isac->mocr |= 0xa0;
  270. WriteISAC(isac, ISAC_MOCR, isac->mocr);
  271. isac->mon_rxp = 0;
  272. pr_debug("%s: ISAC MON RX overflow!\n", isac->name);
  273. goto afterMONR1;
  274. }
  275. isac->mon_rx[isac->mon_rxp++] = ReadISAC(isac, ISAC_MOR1);
  276. pr_debug("%s: ISAC MOR1 %02x\n", isac->name,
  277. isac->mon_rx[isac->mon_rxp - 1]);
  278. isac->mocr |= 0x40;
  279. WriteISAC(isac, ISAC_MOCR, isac->mocr);
  280. }
  281. afterMONR1:
  282. if (val & 0x04) {
  283. isac->mocr &= 0xf0;
  284. WriteISAC(isac, ISAC_MOCR, isac->mocr);
  285. isac->mocr |= 0x0a;
  286. WriteISAC(isac, ISAC_MOCR, isac->mocr);
  287. if (isac->monitor) {
  288. ret = isac->monitor(isac->dch.hw, MONITOR_RX_0,
  289. isac->mon_rx, isac->mon_rxp);
  290. if (ret)
  291. kfree(isac->mon_rx);
  292. } else {
  293. pr_info("%s: MONITOR 0 received %d but no user\n",
  294. isac->name, isac->mon_rxp);
  295. kfree(isac->mon_rx);
  296. }
  297. isac->mon_rx = NULL;
  298. isac->mon_rxp = 0;
  299. }
  300. if (val & 0x40) {
  301. isac->mocr &= 0x0f;
  302. WriteISAC(isac, ISAC_MOCR, isac->mocr);
  303. isac->mocr |= 0xa0;
  304. WriteISAC(isac, ISAC_MOCR, isac->mocr);
  305. if (isac->monitor) {
  306. ret = isac->monitor(isac->dch.hw, MONITOR_RX_1,
  307. isac->mon_rx, isac->mon_rxp);
  308. if (ret)
  309. kfree(isac->mon_rx);
  310. } else {
  311. pr_info("%s: MONITOR 1 received %d but no user\n",
  312. isac->name, isac->mon_rxp);
  313. kfree(isac->mon_rx);
  314. }
  315. isac->mon_rx = NULL;
  316. isac->mon_rxp = 0;
  317. }
  318. if (val & 0x02) {
  319. if ((!isac->mon_tx) || (isac->mon_txc &&
  320. (isac->mon_txp >= isac->mon_txc) && !(val & 0x08))) {
  321. isac->mocr &= 0xf0;
  322. WriteISAC(isac, ISAC_MOCR, isac->mocr);
  323. isac->mocr |= 0x0a;
  324. WriteISAC(isac, ISAC_MOCR, isac->mocr);
  325. if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
  326. if (isac->monitor)
  327. isac->monitor(isac->dch.hw,
  328. MONITOR_TX_0, NULL, 0);
  329. }
  330. kfree(isac->mon_tx);
  331. isac->mon_tx = NULL;
  332. isac->mon_txc = 0;
  333. isac->mon_txp = 0;
  334. goto AfterMOX0;
  335. }
  336. if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
  337. if (isac->monitor)
  338. isac->monitor(isac->dch.hw,
  339. MONITOR_TX_0, NULL, 0);
  340. kfree(isac->mon_tx);
  341. isac->mon_tx = NULL;
  342. isac->mon_txc = 0;
  343. isac->mon_txp = 0;
  344. goto AfterMOX0;
  345. }
  346. WriteISAC(isac, ISAC_MOX0, isac->mon_tx[isac->mon_txp++]);
  347. pr_debug("%s: ISAC %02x -> MOX0\n", isac->name,
  348. isac->mon_tx[isac->mon_txp - 1]);
  349. }
  350. AfterMOX0:
  351. if (val & 0x20) {
  352. if ((!isac->mon_tx) || (isac->mon_txc &&
  353. (isac->mon_txp >= isac->mon_txc) && !(val & 0x80))) {
  354. isac->mocr &= 0x0f;
  355. WriteISAC(isac, ISAC_MOCR, isac->mocr);
  356. isac->mocr |= 0xa0;
  357. WriteISAC(isac, ISAC_MOCR, isac->mocr);
  358. if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
  359. if (isac->monitor)
  360. isac->monitor(isac->dch.hw,
  361. MONITOR_TX_1, NULL, 0);
  362. }
  363. kfree(isac->mon_tx);
  364. isac->mon_tx = NULL;
  365. isac->mon_txc = 0;
  366. isac->mon_txp = 0;
  367. goto AfterMOX1;
  368. }
  369. if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
  370. if (isac->monitor)
  371. isac->monitor(isac->dch.hw,
  372. MONITOR_TX_1, NULL, 0);
  373. kfree(isac->mon_tx);
  374. isac->mon_tx = NULL;
  375. isac->mon_txc = 0;
  376. isac->mon_txp = 0;
  377. goto AfterMOX1;
  378. }
  379. WriteISAC(isac, ISAC_MOX1, isac->mon_tx[isac->mon_txp++]);
  380. pr_debug("%s: ISAC %02x -> MOX1\n", isac->name,
  381. isac->mon_tx[isac->mon_txp - 1]);
  382. }
  383. AfterMOX1:
  384. val = 0; /* dummy to avoid warning */
  385. #endif
  386. }
  387. static void
  388. isac_cisq_irq(struct isac_hw *isac) {
  389. u8 val;
  390. val = ReadISAC(isac, ISAC_CIR0);
  391. pr_debug("%s: ISAC CIR0 %02X\n", isac->name, val);
  392. if (val & 2) {
  393. pr_debug("%s: ph_state change %x->%x\n", isac->name,
  394. isac->state, (val >> 2) & 0xf);
  395. isac->state = (val >> 2) & 0xf;
  396. isac_ph_state_change(isac);
  397. }
  398. if (val & 1) {
  399. val = ReadISAC(isac, ISAC_CIR1);
  400. pr_debug("%s: ISAC CIR1 %02X\n", isac->name, val);
  401. }
  402. }
  403. static void
  404. isacsx_cic_irq(struct isac_hw *isac)
  405. {
  406. u8 val;
  407. val = ReadISAC(isac, ISACX_CIR0);
  408. pr_debug("%s: ISACX CIR0 %02X\n", isac->name, val);
  409. if (val & ISACX_CIR0_CIC0) {
  410. pr_debug("%s: ph_state change %x->%x\n", isac->name,
  411. isac->state, val >> 4);
  412. isac->state = val >> 4;
  413. isac_ph_state_change(isac);
  414. }
  415. }
  416. static void
  417. isacsx_rme_irq(struct isac_hw *isac)
  418. {
  419. int count;
  420. u8 val;
  421. val = ReadISAC(isac, ISACX_RSTAD);
  422. if ((val & (ISACX_RSTAD_VFR |
  423. ISACX_RSTAD_RDO |
  424. ISACX_RSTAD_CRC |
  425. ISACX_RSTAD_RAB))
  426. != (ISACX_RSTAD_VFR | ISACX_RSTAD_CRC)) {
  427. pr_debug("%s: RSTAD %#x, dropped\n", isac->name, val);
  428. #ifdef ERROR_STATISTIC
  429. if (val & ISACX_RSTAD_CRC)
  430. isac->dch.err_rx++;
  431. else
  432. isac->dch.err_crc++;
  433. #endif
  434. WriteISAC(isac, ISACX_CMDRD, ISACX_CMDRD_RMC);
  435. dev_kfree_skb(isac->dch.rx_skb);
  436. isac->dch.rx_skb = NULL;
  437. } else {
  438. count = ReadISAC(isac, ISACX_RBCLD) & 0x1f;
  439. if (count == 0)
  440. count = 32;
  441. isac_empty_fifo(isac, count);
  442. if (isac->dch.rx_skb) {
  443. skb_trim(isac->dch.rx_skb, isac->dch.rx_skb->len - 1);
  444. pr_debug("%s: dchannel received %d\n", isac->name,
  445. isac->dch.rx_skb->len);
  446. recv_Dchannel(&isac->dch);
  447. }
  448. }
  449. }
  450. irqreturn_t
  451. mISDNisac_irq(struct isac_hw *isac, u8 val)
  452. {
  453. if (unlikely(!val))
  454. return IRQ_NONE;
  455. pr_debug("%s: ISAC interrupt %02x\n", isac->name, val);
  456. if (isac->type & IPAC_TYPE_ISACX) {
  457. if (val & ISACX__CIC)
  458. isacsx_cic_irq(isac);
  459. if (val & ISACX__ICD) {
  460. val = ReadISAC(isac, ISACX_ISTAD);
  461. pr_debug("%s: ISTAD %02x\n", isac->name, val);
  462. if (val & ISACX_D_XDU) {
  463. pr_debug("%s: ISAC XDU\n", isac->name);
  464. #ifdef ERROR_STATISTIC
  465. isac->dch.err_tx++;
  466. #endif
  467. isac_retransmit(isac);
  468. }
  469. if (val & ISACX_D_XMR) {
  470. pr_debug("%s: ISAC XMR\n", isac->name);
  471. #ifdef ERROR_STATISTIC
  472. isac->dch.err_tx++;
  473. #endif
  474. isac_retransmit(isac);
  475. }
  476. if (val & ISACX_D_XPR)
  477. isac_xpr_irq(isac);
  478. if (val & ISACX_D_RFO) {
  479. pr_debug("%s: ISAC RFO\n", isac->name);
  480. WriteISAC(isac, ISACX_CMDRD, ISACX_CMDRD_RMC);
  481. }
  482. if (val & ISACX_D_RME)
  483. isacsx_rme_irq(isac);
  484. if (val & ISACX_D_RPF)
  485. isac_empty_fifo(isac, 0x20);
  486. }
  487. } else {
  488. if (val & 0x80) /* RME */
  489. isac_rme_irq(isac);
  490. if (val & 0x40) /* RPF */
  491. isac_empty_fifo(isac, 32);
  492. if (val & 0x10) /* XPR */
  493. isac_xpr_irq(isac);
  494. if (val & 0x04) /* CISQ */
  495. isac_cisq_irq(isac);
  496. if (val & 0x20) /* RSC - never */
  497. pr_debug("%s: ISAC RSC interrupt\n", isac->name);
  498. if (val & 0x02) /* SIN - never */
  499. pr_debug("%s: ISAC SIN interrupt\n", isac->name);
  500. if (val & 0x01) { /* EXI */
  501. val = ReadISAC(isac, ISAC_EXIR);
  502. pr_debug("%s: ISAC EXIR %02x\n", isac->name, val);
  503. if (val & 0x80) /* XMR */
  504. pr_debug("%s: ISAC XMR\n", isac->name);
  505. if (val & 0x40) { /* XDU */
  506. pr_debug("%s: ISAC XDU\n", isac->name);
  507. #ifdef ERROR_STATISTIC
  508. isac->dch.err_tx++;
  509. #endif
  510. isac_retransmit(isac);
  511. }
  512. if (val & 0x04) /* MOS */
  513. isac_mos_irq(isac);
  514. }
  515. }
  516. return IRQ_HANDLED;
  517. }
  518. EXPORT_SYMBOL(mISDNisac_irq);
  519. static int
  520. isac_l1hw(struct mISDNchannel *ch, struct sk_buff *skb)
  521. {
  522. struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D);
  523. struct dchannel *dch = container_of(dev, struct dchannel, dev);
  524. struct isac_hw *isac = container_of(dch, struct isac_hw, dch);
  525. int ret = -EINVAL;
  526. struct mISDNhead *hh = mISDN_HEAD_P(skb);
  527. u32 id;
  528. u_long flags;
  529. switch (hh->prim) {
  530. case PH_DATA_REQ:
  531. spin_lock_irqsave(isac->hwlock, flags);
  532. ret = dchannel_senddata(dch, skb);
  533. if (ret > 0) { /* direct TX */
  534. id = hh->id; /* skb can be freed */
  535. isac_fill_fifo(isac);
  536. ret = 0;
  537. spin_unlock_irqrestore(isac->hwlock, flags);
  538. queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
  539. } else
  540. spin_unlock_irqrestore(isac->hwlock, flags);
  541. return ret;
  542. case PH_ACTIVATE_REQ:
  543. ret = l1_event(dch->l1, hh->prim);
  544. break;
  545. case PH_DEACTIVATE_REQ:
  546. test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags);
  547. ret = l1_event(dch->l1, hh->prim);
  548. break;
  549. }
  550. if (!ret)
  551. dev_kfree_skb(skb);
  552. return ret;
  553. }
  554. static int
  555. isac_ctrl(struct isac_hw *isac, u32 cmd, unsigned long para)
  556. {
  557. u8 tl = 0;
  558. unsigned long flags;
  559. int ret = 0;
  560. switch (cmd) {
  561. case HW_TESTLOOP:
  562. spin_lock_irqsave(isac->hwlock, flags);
  563. if (!(isac->type & IPAC_TYPE_ISACX)) {
  564. /* TODO: implement for IPAC_TYPE_ISACX */
  565. if (para & 1) /* B1 */
  566. tl |= 0x0c;
  567. else if (para & 2) /* B2 */
  568. tl |= 0x3;
  569. /* we only support IOM2 mode */
  570. WriteISAC(isac, ISAC_SPCR, tl);
  571. if (tl)
  572. WriteISAC(isac, ISAC_ADF1, 0x8);
  573. else
  574. WriteISAC(isac, ISAC_ADF1, 0x0);
  575. }
  576. spin_unlock_irqrestore(isac->hwlock, flags);
  577. break;
  578. case HW_TIMER3_VALUE:
  579. ret = l1_event(isac->dch.l1, HW_TIMER3_VALUE | (para & 0xff));
  580. break;
  581. default:
  582. pr_debug("%s: %s unknown command %x %lx\n", isac->name,
  583. __func__, cmd, para);
  584. ret = -1;
  585. }
  586. return ret;
  587. }
  588. static int
  589. isac_l1cmd(struct dchannel *dch, u32 cmd)
  590. {
  591. struct isac_hw *isac = container_of(dch, struct isac_hw, dch);
  592. u_long flags;
  593. pr_debug("%s: cmd(%x) state(%02x)\n", isac->name, cmd, isac->state);
  594. switch (cmd) {
  595. case INFO3_P8:
  596. spin_lock_irqsave(isac->hwlock, flags);
  597. ph_command(isac, ISAC_CMD_AR8);
  598. spin_unlock_irqrestore(isac->hwlock, flags);
  599. break;
  600. case INFO3_P10:
  601. spin_lock_irqsave(isac->hwlock, flags);
  602. ph_command(isac, ISAC_CMD_AR10);
  603. spin_unlock_irqrestore(isac->hwlock, flags);
  604. break;
  605. case HW_RESET_REQ:
  606. spin_lock_irqsave(isac->hwlock, flags);
  607. if ((isac->state == ISAC_IND_EI) ||
  608. (isac->state == ISAC_IND_DR) ||
  609. (isac->state == ISAC_IND_DR6) ||
  610. (isac->state == ISAC_IND_RS))
  611. ph_command(isac, ISAC_CMD_TIM);
  612. else
  613. ph_command(isac, ISAC_CMD_RS);
  614. spin_unlock_irqrestore(isac->hwlock, flags);
  615. break;
  616. case HW_DEACT_REQ:
  617. skb_queue_purge(&dch->squeue);
  618. if (dch->tx_skb) {
  619. dev_kfree_skb(dch->tx_skb);
  620. dch->tx_skb = NULL;
  621. }
  622. dch->tx_idx = 0;
  623. if (dch->rx_skb) {
  624. dev_kfree_skb(dch->rx_skb);
  625. dch->rx_skb = NULL;
  626. }
  627. test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
  628. if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags))
  629. del_timer(&dch->timer);
  630. break;
  631. case HW_POWERUP_REQ:
  632. spin_lock_irqsave(isac->hwlock, flags);
  633. ph_command(isac, ISAC_CMD_TIM);
  634. spin_unlock_irqrestore(isac->hwlock, flags);
  635. break;
  636. case PH_ACTIVATE_IND:
  637. test_and_set_bit(FLG_ACTIVE, &dch->Flags);
  638. _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,
  639. GFP_ATOMIC);
  640. break;
  641. case PH_DEACTIVATE_IND:
  642. test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
  643. _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,
  644. GFP_ATOMIC);
  645. break;
  646. default:
  647. pr_debug("%s: %s unknown command %x\n", isac->name,
  648. __func__, cmd);
  649. return -1;
  650. }
  651. return 0;
  652. }
  653. static void
  654. isac_release(struct isac_hw *isac)
  655. {
  656. if (isac->type & IPAC_TYPE_ISACX)
  657. WriteISAC(isac, ISACX_MASK, 0xff);
  658. else if (isac->type != 0)
  659. WriteISAC(isac, ISAC_MASK, 0xff);
  660. if (isac->dch.timer.function != NULL) {
  661. del_timer(&isac->dch.timer);
  662. isac->dch.timer.function = NULL;
  663. }
  664. kfree(isac->mon_rx);
  665. isac->mon_rx = NULL;
  666. kfree(isac->mon_tx);
  667. isac->mon_tx = NULL;
  668. if (isac->dch.l1)
  669. l1_event(isac->dch.l1, CLOSE_CHANNEL);
  670. mISDN_freedchannel(&isac->dch);
  671. }
  672. static void
  673. dbusy_timer_handler(struct timer_list *t)
  674. {
  675. struct isac_hw *isac = from_timer(isac, t, dch.timer);
  676. int rbch, star;
  677. u_long flags;
  678. if (test_bit(FLG_BUSY_TIMER, &isac->dch.Flags)) {
  679. spin_lock_irqsave(isac->hwlock, flags);
  680. rbch = ReadISAC(isac, ISAC_RBCH);
  681. star = ReadISAC(isac, ISAC_STAR);
  682. pr_debug("%s: D-Channel Busy RBCH %02x STAR %02x\n",
  683. isac->name, rbch, star);
  684. if (rbch & ISAC_RBCH_XAC) /* D-Channel Busy */
  685. test_and_set_bit(FLG_L1_BUSY, &isac->dch.Flags);
  686. else {
  687. /* discard frame; reset transceiver */
  688. test_and_clear_bit(FLG_BUSY_TIMER, &isac->dch.Flags);
  689. if (isac->dch.tx_idx)
  690. isac->dch.tx_idx = 0;
  691. else
  692. pr_info("%s: ISAC D-Channel Busy no tx_idx\n",
  693. isac->name);
  694. /* Transmitter reset */
  695. WriteISAC(isac, ISAC_CMDR, 0x01);
  696. }
  697. spin_unlock_irqrestore(isac->hwlock, flags);
  698. }
  699. }
  700. static int
  701. open_dchannel_caller(struct isac_hw *isac, struct channel_req *rq, void *caller)
  702. {
  703. pr_debug("%s: %s dev(%d) open from %p\n", isac->name, __func__,
  704. isac->dch.dev.id, caller);
  705. if (rq->protocol != ISDN_P_TE_S0)
  706. return -EINVAL;
  707. if (rq->adr.channel == 1)
  708. /* E-Channel not supported */
  709. return -EINVAL;
  710. rq->ch = &isac->dch.dev.D;
  711. rq->ch->protocol = rq->protocol;
  712. if (isac->dch.state == 7)
  713. _queue_data(rq->ch, PH_ACTIVATE_IND, MISDN_ID_ANY,
  714. 0, NULL, GFP_KERNEL);
  715. return 0;
  716. }
  717. static int
  718. open_dchannel(struct isac_hw *isac, struct channel_req *rq)
  719. {
  720. return open_dchannel_caller(isac, rq, __builtin_return_address(0));
  721. }
  722. static const char *ISACVer[] =
  723. {"2086/2186 V1.1", "2085 B1", "2085 B2",
  724. "2085 V2.3"};
  725. static int
  726. isac_init(struct isac_hw *isac)
  727. {
  728. u8 val;
  729. int err = 0;
  730. if (!isac->dch.l1) {
  731. err = create_l1(&isac->dch, isac_l1cmd);
  732. if (err)
  733. return err;
  734. }
  735. isac->mon_tx = NULL;
  736. isac->mon_rx = NULL;
  737. timer_setup(&isac->dch.timer, dbusy_timer_handler, 0);
  738. isac->mocr = 0xaa;
  739. if (isac->type & IPAC_TYPE_ISACX) {
  740. /* Disable all IRQ */
  741. WriteISAC(isac, ISACX_MASK, 0xff);
  742. val = ReadISAC(isac, ISACX_STARD);
  743. pr_debug("%s: ISACX STARD %x\n", isac->name, val);
  744. val = ReadISAC(isac, ISACX_ISTAD);
  745. pr_debug("%s: ISACX ISTAD %x\n", isac->name, val);
  746. val = ReadISAC(isac, ISACX_ISTA);
  747. pr_debug("%s: ISACX ISTA %x\n", isac->name, val);
  748. /* clear LDD */
  749. WriteISAC(isac, ISACX_TR_CONF0, 0x00);
  750. /* enable transmitter */
  751. WriteISAC(isac, ISACX_TR_CONF2, 0x00);
  752. /* transparent mode 0, RAC, stop/go */
  753. WriteISAC(isac, ISACX_MODED, 0xc9);
  754. /* all HDLC IRQ unmasked */
  755. val = ReadISAC(isac, ISACX_ID);
  756. if (isac->dch.debug & DEBUG_HW)
  757. pr_notice("%s: ISACX Design ID %x\n",
  758. isac->name, val & 0x3f);
  759. val = ReadISAC(isac, ISACX_CIR0);
  760. pr_debug("%s: ISACX CIR0 %02X\n", isac->name, val);
  761. isac->state = val >> 4;
  762. isac_ph_state_change(isac);
  763. ph_command(isac, ISAC_CMD_RS);
  764. WriteISAC(isac, ISACX_MASK, IPACX__ON);
  765. WriteISAC(isac, ISACX_MASKD, 0x00);
  766. } else { /* old isac */
  767. WriteISAC(isac, ISAC_MASK, 0xff);
  768. val = ReadISAC(isac, ISAC_STAR);
  769. pr_debug("%s: ISAC STAR %x\n", isac->name, val);
  770. val = ReadISAC(isac, ISAC_MODE);
  771. pr_debug("%s: ISAC MODE %x\n", isac->name, val);
  772. val = ReadISAC(isac, ISAC_ADF2);
  773. pr_debug("%s: ISAC ADF2 %x\n", isac->name, val);
  774. val = ReadISAC(isac, ISAC_ISTA);
  775. pr_debug("%s: ISAC ISTA %x\n", isac->name, val);
  776. if (val & 0x01) {
  777. val = ReadISAC(isac, ISAC_EXIR);
  778. pr_debug("%s: ISAC EXIR %x\n", isac->name, val);
  779. }
  780. val = ReadISAC(isac, ISAC_RBCH);
  781. if (isac->dch.debug & DEBUG_HW)
  782. pr_notice("%s: ISAC version (%x): %s\n", isac->name,
  783. val, ISACVer[(val >> 5) & 3]);
  784. isac->type |= ((val >> 5) & 3);
  785. if (!isac->adf2)
  786. isac->adf2 = 0x80;
  787. if (!(isac->adf2 & 0x80)) { /* only IOM 2 Mode */
  788. pr_info("%s: only support IOM2 mode but adf2=%02x\n",
  789. isac->name, isac->adf2);
  790. isac_release(isac);
  791. return -EINVAL;
  792. }
  793. WriteISAC(isac, ISAC_ADF2, isac->adf2);
  794. WriteISAC(isac, ISAC_SQXR, 0x2f);
  795. WriteISAC(isac, ISAC_SPCR, 0x00);
  796. WriteISAC(isac, ISAC_STCR, 0x70);
  797. WriteISAC(isac, ISAC_MODE, 0xc9);
  798. WriteISAC(isac, ISAC_TIMR, 0x00);
  799. WriteISAC(isac, ISAC_ADF1, 0x00);
  800. val = ReadISAC(isac, ISAC_CIR0);
  801. pr_debug("%s: ISAC CIR0 %x\n", isac->name, val);
  802. isac->state = (val >> 2) & 0xf;
  803. isac_ph_state_change(isac);
  804. ph_command(isac, ISAC_CMD_RS);
  805. WriteISAC(isac, ISAC_MASK, 0);
  806. }
  807. return err;
  808. }
  809. int
  810. mISDNisac_init(struct isac_hw *isac, void *hw)
  811. {
  812. mISDN_initdchannel(&isac->dch, MAX_DFRAME_LEN_L1, isac_ph_state_bh);
  813. isac->dch.hw = hw;
  814. isac->dch.dev.D.send = isac_l1hw;
  815. isac->init = isac_init;
  816. isac->release = isac_release;
  817. isac->ctrl = isac_ctrl;
  818. isac->open = open_dchannel;
  819. isac->dch.dev.Dprotocols = (1 << ISDN_P_TE_S0);
  820. isac->dch.dev.nrbchan = 2;
  821. return 0;
  822. }
  823. EXPORT_SYMBOL(mISDNisac_init);
  824. static void
  825. waitforCEC(struct hscx_hw *hx)
  826. {
  827. u8 starb, to = 50;
  828. while (to) {
  829. starb = ReadHSCX(hx, IPAC_STARB);
  830. if (!(starb & 0x04))
  831. break;
  832. udelay(1);
  833. to--;
  834. }
  835. if (to < 50)
  836. pr_debug("%s: B%1d CEC %d us\n", hx->ip->name, hx->bch.nr,
  837. 50 - to);
  838. if (!to)
  839. pr_info("%s: B%1d CEC timeout\n", hx->ip->name, hx->bch.nr);
  840. }
  841. static void
  842. waitforXFW(struct hscx_hw *hx)
  843. {
  844. u8 starb, to = 50;
  845. while (to) {
  846. starb = ReadHSCX(hx, IPAC_STARB);
  847. if ((starb & 0x44) == 0x40)
  848. break;
  849. udelay(1);
  850. to--;
  851. }
  852. if (to < 50)
  853. pr_debug("%s: B%1d XFW %d us\n", hx->ip->name, hx->bch.nr,
  854. 50 - to);
  855. if (!to)
  856. pr_info("%s: B%1d XFW timeout\n", hx->ip->name, hx->bch.nr);
  857. }
  858. static void
  859. hscx_cmdr(struct hscx_hw *hx, u8 cmd)
  860. {
  861. if (hx->ip->type & IPAC_TYPE_IPACX)
  862. WriteHSCX(hx, IPACX_CMDRB, cmd);
  863. else {
  864. waitforCEC(hx);
  865. WriteHSCX(hx, IPAC_CMDRB, cmd);
  866. }
  867. }
  868. static void
  869. hscx_empty_fifo(struct hscx_hw *hscx, u8 count)
  870. {
  871. u8 *p;
  872. int maxlen;
  873. pr_debug("%s: B%1d %d\n", hscx->ip->name, hscx->bch.nr, count);
  874. if (test_bit(FLG_RX_OFF, &hscx->bch.Flags)) {
  875. hscx->bch.dropcnt += count;
  876. hscx_cmdr(hscx, 0x80); /* RMC */
  877. return;
  878. }
  879. maxlen = bchannel_get_rxbuf(&hscx->bch, count);
  880. if (maxlen < 0) {
  881. hscx_cmdr(hscx, 0x80); /* RMC */
  882. if (hscx->bch.rx_skb)
  883. skb_trim(hscx->bch.rx_skb, 0);
  884. pr_warn("%s.B%d: No bufferspace for %d bytes\n",
  885. hscx->ip->name, hscx->bch.nr, count);
  886. return;
  887. }
  888. p = skb_put(hscx->bch.rx_skb, count);
  889. if (hscx->ip->type & IPAC_TYPE_IPACX)
  890. hscx->ip->read_fifo(hscx->ip->hw,
  891. hscx->off + IPACX_RFIFOB, p, count);
  892. else
  893. hscx->ip->read_fifo(hscx->ip->hw,
  894. hscx->off, p, count);
  895. hscx_cmdr(hscx, 0x80); /* RMC */
  896. if (hscx->bch.debug & DEBUG_HW_BFIFO) {
  897. snprintf(hscx->log, 64, "B%1d-recv %s %d ",
  898. hscx->bch.nr, hscx->ip->name, count);
  899. print_hex_dump_bytes(hscx->log, DUMP_PREFIX_OFFSET, p, count);
  900. }
  901. }
  902. static void
  903. hscx_fill_fifo(struct hscx_hw *hscx)
  904. {
  905. int count, more;
  906. u8 *p;
  907. if (!hscx->bch.tx_skb) {
  908. if (!test_bit(FLG_TX_EMPTY, &hscx->bch.Flags))
  909. return;
  910. count = hscx->fifo_size;
  911. more = 1;
  912. p = hscx->log;
  913. memset(p, hscx->bch.fill[0], count);
  914. } else {
  915. count = hscx->bch.tx_skb->len - hscx->bch.tx_idx;
  916. if (count <= 0)
  917. return;
  918. p = hscx->bch.tx_skb->data + hscx->bch.tx_idx;
  919. more = test_bit(FLG_TRANSPARENT, &hscx->bch.Flags) ? 1 : 0;
  920. if (count > hscx->fifo_size) {
  921. count = hscx->fifo_size;
  922. more = 1;
  923. }
  924. pr_debug("%s: B%1d %d/%d/%d\n", hscx->ip->name, hscx->bch.nr,
  925. count, hscx->bch.tx_idx, hscx->bch.tx_skb->len);
  926. hscx->bch.tx_idx += count;
  927. }
  928. if (hscx->ip->type & IPAC_TYPE_IPACX)
  929. hscx->ip->write_fifo(hscx->ip->hw,
  930. hscx->off + IPACX_XFIFOB, p, count);
  931. else {
  932. waitforXFW(hscx);
  933. hscx->ip->write_fifo(hscx->ip->hw,
  934. hscx->off, p, count);
  935. }
  936. hscx_cmdr(hscx, more ? 0x08 : 0x0a);
  937. if (hscx->bch.tx_skb && (hscx->bch.debug & DEBUG_HW_BFIFO)) {
  938. snprintf(hscx->log, 64, "B%1d-send %s %d ",
  939. hscx->bch.nr, hscx->ip->name, count);
  940. print_hex_dump_bytes(hscx->log, DUMP_PREFIX_OFFSET, p, count);
  941. }
  942. }
  943. static void
  944. hscx_xpr(struct hscx_hw *hx)
  945. {
  946. if (hx->bch.tx_skb && hx->bch.tx_idx < hx->bch.tx_skb->len) {
  947. hscx_fill_fifo(hx);
  948. } else {
  949. dev_kfree_skb(hx->bch.tx_skb);
  950. if (get_next_bframe(&hx->bch)) {
  951. hscx_fill_fifo(hx);
  952. test_and_clear_bit(FLG_TX_EMPTY, &hx->bch.Flags);
  953. } else if (test_bit(FLG_TX_EMPTY, &hx->bch.Flags)) {
  954. hscx_fill_fifo(hx);
  955. }
  956. }
  957. }
  958. static void
  959. ipac_rme(struct hscx_hw *hx)
  960. {
  961. int count;
  962. u8 rstab;
  963. if (hx->ip->type & IPAC_TYPE_IPACX)
  964. rstab = ReadHSCX(hx, IPACX_RSTAB);
  965. else
  966. rstab = ReadHSCX(hx, IPAC_RSTAB);
  967. pr_debug("%s: B%1d RSTAB %02x\n", hx->ip->name, hx->bch.nr, rstab);
  968. if ((rstab & 0xf0) != 0xa0) {
  969. /* !(VFR && !RDO && CRC && !RAB) */
  970. if (!(rstab & 0x80)) {
  971. if (hx->bch.debug & DEBUG_HW_BCHANNEL)
  972. pr_notice("%s: B%1d invalid frame\n",
  973. hx->ip->name, hx->bch.nr);
  974. }
  975. if (rstab & 0x40) {
  976. if (hx->bch.debug & DEBUG_HW_BCHANNEL)
  977. pr_notice("%s: B%1d RDO proto=%x\n",
  978. hx->ip->name, hx->bch.nr,
  979. hx->bch.state);
  980. }
  981. if (!(rstab & 0x20)) {
  982. if (hx->bch.debug & DEBUG_HW_BCHANNEL)
  983. pr_notice("%s: B%1d CRC error\n",
  984. hx->ip->name, hx->bch.nr);
  985. }
  986. hscx_cmdr(hx, 0x80); /* Do RMC */
  987. return;
  988. }
  989. if (hx->ip->type & IPAC_TYPE_IPACX)
  990. count = ReadHSCX(hx, IPACX_RBCLB);
  991. else
  992. count = ReadHSCX(hx, IPAC_RBCLB);
  993. count &= (hx->fifo_size - 1);
  994. if (count == 0)
  995. count = hx->fifo_size;
  996. hscx_empty_fifo(hx, count);
  997. if (!hx->bch.rx_skb)
  998. return;
  999. if (hx->bch.rx_skb->len < 2) {
  1000. pr_debug("%s: B%1d frame too short %d\n",
  1001. hx->ip->name, hx->bch.nr, hx->bch.rx_skb->len);
  1002. skb_trim(hx->bch.rx_skb, 0);
  1003. } else {
  1004. skb_trim(hx->bch.rx_skb, hx->bch.rx_skb->len - 1);
  1005. recv_Bchannel(&hx->bch, 0, false);
  1006. }
  1007. }
  1008. static void
  1009. ipac_irq(struct hscx_hw *hx, u8 ista)
  1010. {
  1011. u8 istab, m, exirb = 0;
  1012. if (hx->ip->type & IPAC_TYPE_IPACX)
  1013. istab = ReadHSCX(hx, IPACX_ISTAB);
  1014. else if (hx->ip->type & IPAC_TYPE_IPAC) {
  1015. istab = ReadHSCX(hx, IPAC_ISTAB);
  1016. m = (hx->bch.nr & 1) ? IPAC__EXA : IPAC__EXB;
  1017. if (m & ista) {
  1018. exirb = ReadHSCX(hx, IPAC_EXIRB);
  1019. pr_debug("%s: B%1d EXIRB %02x\n", hx->ip->name,
  1020. hx->bch.nr, exirb);
  1021. }
  1022. } else if (hx->bch.nr & 2) { /* HSCX B */
  1023. if (ista & (HSCX__EXA | HSCX__ICA))
  1024. ipac_irq(&hx->ip->hscx[0], ista);
  1025. if (ista & HSCX__EXB) {
  1026. exirb = ReadHSCX(hx, IPAC_EXIRB);
  1027. pr_debug("%s: B%1d EXIRB %02x\n", hx->ip->name,
  1028. hx->bch.nr, exirb);
  1029. }
  1030. istab = ista & 0xF8;
  1031. } else { /* HSCX A */
  1032. istab = ReadHSCX(hx, IPAC_ISTAB);
  1033. if (ista & HSCX__EXA) {
  1034. exirb = ReadHSCX(hx, IPAC_EXIRB);
  1035. pr_debug("%s: B%1d EXIRB %02x\n", hx->ip->name,
  1036. hx->bch.nr, exirb);
  1037. }
  1038. istab = istab & 0xF8;
  1039. }
  1040. if (exirb & IPAC_B_XDU)
  1041. istab |= IPACX_B_XDU;
  1042. if (exirb & IPAC_B_RFO)
  1043. istab |= IPACX_B_RFO;
  1044. pr_debug("%s: B%1d ISTAB %02x\n", hx->ip->name, hx->bch.nr, istab);
  1045. if (!test_bit(FLG_ACTIVE, &hx->bch.Flags))
  1046. return;
  1047. if (istab & IPACX_B_RME)
  1048. ipac_rme(hx);
  1049. if (istab & IPACX_B_RPF) {
  1050. hscx_empty_fifo(hx, hx->fifo_size);
  1051. if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags))
  1052. recv_Bchannel(&hx->bch, 0, false);
  1053. }
  1054. if (istab & IPACX_B_RFO) {
  1055. pr_debug("%s: B%1d RFO error\n", hx->ip->name, hx->bch.nr);
  1056. hscx_cmdr(hx, 0x40); /* RRES */
  1057. }
  1058. if (istab & IPACX_B_XPR)
  1059. hscx_xpr(hx);
  1060. if (istab & IPACX_B_XDU) {
  1061. if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) {
  1062. if (test_bit(FLG_FILLEMPTY, &hx->bch.Flags))
  1063. test_and_set_bit(FLG_TX_EMPTY, &hx->bch.Flags);
  1064. hscx_xpr(hx);
  1065. return;
  1066. }
  1067. pr_debug("%s: B%1d XDU error at len %d\n", hx->ip->name,
  1068. hx->bch.nr, hx->bch.tx_idx);
  1069. hx->bch.tx_idx = 0;
  1070. hscx_cmdr(hx, 0x01); /* XRES */
  1071. }
  1072. }
  1073. irqreturn_t
  1074. mISDNipac_irq(struct ipac_hw *ipac, int maxloop)
  1075. {
  1076. int cnt = maxloop + 1;
  1077. u8 ista, istad;
  1078. struct isac_hw *isac = &ipac->isac;
  1079. if (ipac->type & IPAC_TYPE_IPACX) {
  1080. ista = ReadIPAC(ipac, ISACX_ISTA);
  1081. while (ista && --cnt) {
  1082. pr_debug("%s: ISTA %02x\n", ipac->name, ista);
  1083. if (ista & IPACX__ICA)
  1084. ipac_irq(&ipac->hscx[0], ista);
  1085. if (ista & IPACX__ICB)
  1086. ipac_irq(&ipac->hscx[1], ista);
  1087. if (ista & (ISACX__ICD | ISACX__CIC))
  1088. mISDNisac_irq(&ipac->isac, ista);
  1089. ista = ReadIPAC(ipac, ISACX_ISTA);
  1090. }
  1091. } else if (ipac->type & IPAC_TYPE_IPAC) {
  1092. ista = ReadIPAC(ipac, IPAC_ISTA);
  1093. while (ista && --cnt) {
  1094. pr_debug("%s: ISTA %02x\n", ipac->name, ista);
  1095. if (ista & (IPAC__ICD | IPAC__EXD)) {
  1096. istad = ReadISAC(isac, ISAC_ISTA);
  1097. pr_debug("%s: ISTAD %02x\n", ipac->name, istad);
  1098. if (istad & IPAC_D_TIN2)
  1099. pr_debug("%s TIN2 irq\n", ipac->name);
  1100. if (ista & IPAC__EXD)
  1101. istad |= 1; /* ISAC EXI */
  1102. mISDNisac_irq(isac, istad);
  1103. }
  1104. if (ista & (IPAC__ICA | IPAC__EXA))
  1105. ipac_irq(&ipac->hscx[0], ista);
  1106. if (ista & (IPAC__ICB | IPAC__EXB))
  1107. ipac_irq(&ipac->hscx[1], ista);
  1108. ista = ReadIPAC(ipac, IPAC_ISTA);
  1109. }
  1110. } else if (ipac->type & IPAC_TYPE_HSCX) {
  1111. while (--cnt) {
  1112. ista = ReadIPAC(ipac, IPAC_ISTAB + ipac->hscx[1].off);
  1113. pr_debug("%s: B2 ISTA %02x\n", ipac->name, ista);
  1114. if (ista)
  1115. ipac_irq(&ipac->hscx[1], ista);
  1116. istad = ReadISAC(isac, ISAC_ISTA);
  1117. pr_debug("%s: ISTAD %02x\n", ipac->name, istad);
  1118. if (istad)
  1119. mISDNisac_irq(isac, istad);
  1120. if (0 == (ista | istad))
  1121. break;
  1122. }
  1123. }
  1124. if (cnt > maxloop) /* only for ISAC/HSCX without PCI IRQ test */
  1125. return IRQ_NONE;
  1126. if (cnt < maxloop)
  1127. pr_debug("%s: %d irqloops cpu%d\n", ipac->name,
  1128. maxloop - cnt, smp_processor_id());
  1129. if (maxloop && !cnt)
  1130. pr_notice("%s: %d IRQ LOOP cpu%d\n", ipac->name,
  1131. maxloop, smp_processor_id());
  1132. return IRQ_HANDLED;
  1133. }
  1134. EXPORT_SYMBOL(mISDNipac_irq);
  1135. static int
  1136. hscx_mode(struct hscx_hw *hscx, u32 bprotocol)
  1137. {
  1138. pr_debug("%s: HSCX %c protocol %x-->%x ch %d\n", hscx->ip->name,
  1139. '@' + hscx->bch.nr, hscx->bch.state, bprotocol, hscx->bch.nr);
  1140. if (hscx->ip->type & IPAC_TYPE_IPACX) {
  1141. if (hscx->bch.nr & 1) { /* B1 and ICA */
  1142. WriteIPAC(hscx->ip, ISACX_BCHA_TSDP_BC1, 0x80);
  1143. WriteIPAC(hscx->ip, ISACX_BCHA_CR, 0x88);
  1144. } else { /* B2 and ICB */
  1145. WriteIPAC(hscx->ip, ISACX_BCHB_TSDP_BC1, 0x81);
  1146. WriteIPAC(hscx->ip, ISACX_BCHB_CR, 0x88);
  1147. }
  1148. switch (bprotocol) {
  1149. case ISDN_P_NONE: /* init */
  1150. WriteHSCX(hscx, IPACX_MODEB, 0xC0); /* rec off */
  1151. WriteHSCX(hscx, IPACX_EXMB, 0x30); /* std adj. */
  1152. WriteHSCX(hscx, IPACX_MASKB, 0xFF); /* ints off */
  1153. hscx_cmdr(hscx, 0x41);
  1154. test_and_clear_bit(FLG_HDLC, &hscx->bch.Flags);
  1155. test_and_clear_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
  1156. break;
  1157. case ISDN_P_B_RAW:
  1158. WriteHSCX(hscx, IPACX_MODEB, 0x88); /* ex trans */
  1159. WriteHSCX(hscx, IPACX_EXMB, 0x00); /* trans */
  1160. hscx_cmdr(hscx, 0x41);
  1161. WriteHSCX(hscx, IPACX_MASKB, IPACX_B_ON);
  1162. test_and_set_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
  1163. break;
  1164. case ISDN_P_B_HDLC:
  1165. WriteHSCX(hscx, IPACX_MODEB, 0xC0); /* trans */
  1166. WriteHSCX(hscx, IPACX_EXMB, 0x00); /* hdlc,crc */
  1167. hscx_cmdr(hscx, 0x41);
  1168. WriteHSCX(hscx, IPACX_MASKB, IPACX_B_ON);
  1169. test_and_set_bit(FLG_HDLC, &hscx->bch.Flags);
  1170. break;
  1171. default:
  1172. pr_info("%s: protocol not known %x\n", hscx->ip->name,
  1173. bprotocol);
  1174. return -ENOPROTOOPT;
  1175. }
  1176. } else if (hscx->ip->type & IPAC_TYPE_IPAC) { /* IPAC */
  1177. WriteHSCX(hscx, IPAC_CCR1, 0x82);
  1178. WriteHSCX(hscx, IPAC_CCR2, 0x30);
  1179. WriteHSCX(hscx, IPAC_XCCR, 0x07);
  1180. WriteHSCX(hscx, IPAC_RCCR, 0x07);
  1181. WriteHSCX(hscx, IPAC_TSAX, hscx->slot);
  1182. WriteHSCX(hscx, IPAC_TSAR, hscx->slot);
  1183. switch (bprotocol) {
  1184. case ISDN_P_NONE:
  1185. WriteHSCX(hscx, IPAC_TSAX, 0x1F);
  1186. WriteHSCX(hscx, IPAC_TSAR, 0x1F);
  1187. WriteHSCX(hscx, IPAC_MODEB, 0x84);
  1188. WriteHSCX(hscx, IPAC_CCR1, 0x82);
  1189. WriteHSCX(hscx, IPAC_MASKB, 0xFF); /* ints off */
  1190. test_and_clear_bit(FLG_HDLC, &hscx->bch.Flags);
  1191. test_and_clear_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
  1192. break;
  1193. case ISDN_P_B_RAW:
  1194. WriteHSCX(hscx, IPAC_MODEB, 0xe4); /* ex trans */
  1195. WriteHSCX(hscx, IPAC_CCR1, 0x82);
  1196. hscx_cmdr(hscx, 0x41);
  1197. WriteHSCX(hscx, IPAC_MASKB, 0);
  1198. test_and_set_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
  1199. break;
  1200. case ISDN_P_B_HDLC:
  1201. WriteHSCX(hscx, IPAC_MODEB, 0x8c);
  1202. WriteHSCX(hscx, IPAC_CCR1, 0x8a);
  1203. hscx_cmdr(hscx, 0x41);
  1204. WriteHSCX(hscx, IPAC_MASKB, 0);
  1205. test_and_set_bit(FLG_HDLC, &hscx->bch.Flags);
  1206. break;
  1207. default:
  1208. pr_info("%s: protocol not known %x\n", hscx->ip->name,
  1209. bprotocol);
  1210. return -ENOPROTOOPT;
  1211. }
  1212. } else if (hscx->ip->type & IPAC_TYPE_HSCX) { /* HSCX */
  1213. WriteHSCX(hscx, IPAC_CCR1, 0x85);
  1214. WriteHSCX(hscx, IPAC_CCR2, 0x30);
  1215. WriteHSCX(hscx, IPAC_XCCR, 0x07);
  1216. WriteHSCX(hscx, IPAC_RCCR, 0x07);
  1217. WriteHSCX(hscx, IPAC_TSAX, hscx->slot);
  1218. WriteHSCX(hscx, IPAC_TSAR, hscx->slot);
  1219. switch (bprotocol) {
  1220. case ISDN_P_NONE:
  1221. WriteHSCX(hscx, IPAC_TSAX, 0x1F);
  1222. WriteHSCX(hscx, IPAC_TSAR, 0x1F);
  1223. WriteHSCX(hscx, IPAC_MODEB, 0x84);
  1224. WriteHSCX(hscx, IPAC_CCR1, 0x85);
  1225. WriteHSCX(hscx, IPAC_MASKB, 0xFF); /* ints off */
  1226. test_and_clear_bit(FLG_HDLC, &hscx->bch.Flags);
  1227. test_and_clear_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
  1228. break;
  1229. case ISDN_P_B_RAW:
  1230. WriteHSCX(hscx, IPAC_MODEB, 0xe4); /* ex trans */
  1231. WriteHSCX(hscx, IPAC_CCR1, 0x85);
  1232. hscx_cmdr(hscx, 0x41);
  1233. WriteHSCX(hscx, IPAC_MASKB, 0);
  1234. test_and_set_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
  1235. break;
  1236. case ISDN_P_B_HDLC:
  1237. WriteHSCX(hscx, IPAC_MODEB, 0x8c);
  1238. WriteHSCX(hscx, IPAC_CCR1, 0x8d);
  1239. hscx_cmdr(hscx, 0x41);
  1240. WriteHSCX(hscx, IPAC_MASKB, 0);
  1241. test_and_set_bit(FLG_HDLC, &hscx->bch.Flags);
  1242. break;
  1243. default:
  1244. pr_info("%s: protocol not known %x\n", hscx->ip->name,
  1245. bprotocol);
  1246. return -ENOPROTOOPT;
  1247. }
  1248. } else
  1249. return -EINVAL;
  1250. hscx->bch.state = bprotocol;
  1251. return 0;
  1252. }
  1253. static int
  1254. hscx_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
  1255. {
  1256. struct bchannel *bch = container_of(ch, struct bchannel, ch);
  1257. struct hscx_hw *hx = container_of(bch, struct hscx_hw, bch);
  1258. int ret = -EINVAL;
  1259. struct mISDNhead *hh = mISDN_HEAD_P(skb);
  1260. unsigned long flags;
  1261. switch (hh->prim) {
  1262. case PH_DATA_REQ:
  1263. spin_lock_irqsave(hx->ip->hwlock, flags);
  1264. ret = bchannel_senddata(bch, skb);
  1265. if (ret > 0) { /* direct TX */
  1266. ret = 0;
  1267. hscx_fill_fifo(hx);
  1268. }
  1269. spin_unlock_irqrestore(hx->ip->hwlock, flags);
  1270. return ret;
  1271. case PH_ACTIVATE_REQ:
  1272. spin_lock_irqsave(hx->ip->hwlock, flags);
  1273. if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags))
  1274. ret = hscx_mode(hx, ch->protocol);
  1275. else
  1276. ret = 0;
  1277. spin_unlock_irqrestore(hx->ip->hwlock, flags);
  1278. if (!ret)
  1279. _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0,
  1280. NULL, GFP_KERNEL);
  1281. break;
  1282. case PH_DEACTIVATE_REQ:
  1283. spin_lock_irqsave(hx->ip->hwlock, flags);
  1284. mISDN_clear_bchannel(bch);
  1285. hscx_mode(hx, ISDN_P_NONE);
  1286. spin_unlock_irqrestore(hx->ip->hwlock, flags);
  1287. _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,
  1288. NULL, GFP_KERNEL);
  1289. ret = 0;
  1290. break;
  1291. default:
  1292. pr_info("%s: %s unknown prim(%x,%x)\n",
  1293. hx->ip->name, __func__, hh->prim, hh->id);
  1294. ret = -EINVAL;
  1295. }
  1296. if (!ret)
  1297. dev_kfree_skb(skb);
  1298. return ret;
  1299. }
  1300. static int
  1301. channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
  1302. {
  1303. return mISDN_ctrl_bchannel(bch, cq);
  1304. }
  1305. static int
  1306. hscx_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
  1307. {
  1308. struct bchannel *bch = container_of(ch, struct bchannel, ch);
  1309. struct hscx_hw *hx = container_of(bch, struct hscx_hw, bch);
  1310. int ret = -EINVAL;
  1311. u_long flags;
  1312. pr_debug("%s: %s cmd:%x %p\n", hx->ip->name, __func__, cmd, arg);
  1313. switch (cmd) {
  1314. case CLOSE_CHANNEL:
  1315. test_and_clear_bit(FLG_OPEN, &bch->Flags);
  1316. cancel_work_sync(&bch->workq);
  1317. spin_lock_irqsave(hx->ip->hwlock, flags);
  1318. mISDN_clear_bchannel(bch);
  1319. hscx_mode(hx, ISDN_P_NONE);
  1320. spin_unlock_irqrestore(hx->ip->hwlock, flags);
  1321. ch->protocol = ISDN_P_NONE;
  1322. ch->peer = NULL;
  1323. module_put(hx->ip->owner);
  1324. ret = 0;
  1325. break;
  1326. case CONTROL_CHANNEL:
  1327. ret = channel_bctrl(bch, arg);
  1328. break;
  1329. default:
  1330. pr_info("%s: %s unknown prim(%x)\n",
  1331. hx->ip->name, __func__, cmd);
  1332. }
  1333. return ret;
  1334. }
  1335. static void
  1336. free_ipac(struct ipac_hw *ipac)
  1337. {
  1338. isac_release(&ipac->isac);
  1339. }
  1340. static const char *HSCXVer[] =
  1341. {"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7",
  1342. "?8", "?9", "?10", "?11", "?12", "?13", "?14", "???"};
  1343. static void
  1344. hscx_init(struct hscx_hw *hx)
  1345. {
  1346. u8 val;
  1347. WriteHSCX(hx, IPAC_RAH2, 0xFF);
  1348. WriteHSCX(hx, IPAC_XBCH, 0x00);
  1349. WriteHSCX(hx, IPAC_RLCR, 0x00);
  1350. if (hx->ip->type & IPAC_TYPE_HSCX) {
  1351. WriteHSCX(hx, IPAC_CCR1, 0x85);
  1352. val = ReadHSCX(hx, HSCX_VSTR);
  1353. pr_debug("%s: HSCX VSTR %02x\n", hx->ip->name, val);
  1354. if (hx->bch.debug & DEBUG_HW)
  1355. pr_notice("%s: HSCX version %s\n", hx->ip->name,
  1356. HSCXVer[val & 0x0f]);
  1357. } else
  1358. WriteHSCX(hx, IPAC_CCR1, 0x82);
  1359. WriteHSCX(hx, IPAC_CCR2, 0x30);
  1360. WriteHSCX(hx, IPAC_XCCR, 0x07);
  1361. WriteHSCX(hx, IPAC_RCCR, 0x07);
  1362. }
  1363. static int
  1364. ipac_init(struct ipac_hw *ipac)
  1365. {
  1366. u8 val;
  1367. if (ipac->type & IPAC_TYPE_HSCX) {
  1368. hscx_init(&ipac->hscx[0]);
  1369. hscx_init(&ipac->hscx[1]);
  1370. val = ReadIPAC(ipac, IPAC_ID);
  1371. } else if (ipac->type & IPAC_TYPE_IPAC) {
  1372. hscx_init(&ipac->hscx[0]);
  1373. hscx_init(&ipac->hscx[1]);
  1374. WriteIPAC(ipac, IPAC_MASK, IPAC__ON);
  1375. val = ReadIPAC(ipac, IPAC_CONF);
  1376. /* conf is default 0, but can be overwritten by card setup */
  1377. pr_debug("%s: IPAC CONF %02x/%02x\n", ipac->name,
  1378. val, ipac->conf);
  1379. WriteIPAC(ipac, IPAC_CONF, ipac->conf);
  1380. val = ReadIPAC(ipac, IPAC_ID);
  1381. if (ipac->hscx[0].bch.debug & DEBUG_HW)
  1382. pr_notice("%s: IPAC Design ID %02x\n", ipac->name, val);
  1383. }
  1384. /* nothing special for IPACX to do here */
  1385. return isac_init(&ipac->isac);
  1386. }
  1387. static int
  1388. open_bchannel(struct ipac_hw *ipac, struct channel_req *rq)
  1389. {
  1390. struct bchannel *bch;
  1391. if (rq->adr.channel == 0 || rq->adr.channel > 2)
  1392. return -EINVAL;
  1393. if (rq->protocol == ISDN_P_NONE)
  1394. return -EINVAL;
  1395. bch = &ipac->hscx[rq->adr.channel - 1].bch;
  1396. if (test_and_set_bit(FLG_OPEN, &bch->Flags))
  1397. return -EBUSY; /* b-channel can be only open once */
  1398. test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
  1399. bch->ch.protocol = rq->protocol;
  1400. rq->ch = &bch->ch;
  1401. return 0;
  1402. }
  1403. static int
  1404. channel_ctrl(struct ipac_hw *ipac, struct mISDN_ctrl_req *cq)
  1405. {
  1406. int ret = 0;
  1407. switch (cq->op) {
  1408. case MISDN_CTRL_GETOP:
  1409. cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_L1_TIMER3;
  1410. break;
  1411. case MISDN_CTRL_LOOP:
  1412. /* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
  1413. if (cq->channel < 0 || cq->channel > 3) {
  1414. ret = -EINVAL;
  1415. break;
  1416. }
  1417. ret = ipac->ctrl(ipac, HW_TESTLOOP, cq->channel);
  1418. break;
  1419. case MISDN_CTRL_L1_TIMER3:
  1420. ret = ipac->isac.ctrl(&ipac->isac, HW_TIMER3_VALUE, cq->p1);
  1421. break;
  1422. default:
  1423. pr_info("%s: unknown CTRL OP %x\n", ipac->name, cq->op);
  1424. ret = -EINVAL;
  1425. break;
  1426. }
  1427. return ret;
  1428. }
  1429. static int
  1430. ipac_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
  1431. {
  1432. struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D);
  1433. struct dchannel *dch = container_of(dev, struct dchannel, dev);
  1434. struct isac_hw *isac = container_of(dch, struct isac_hw, dch);
  1435. struct ipac_hw *ipac = container_of(isac, struct ipac_hw, isac);
  1436. struct channel_req *rq;
  1437. int err = 0;
  1438. pr_debug("%s: DCTRL: %x %p\n", ipac->name, cmd, arg);
  1439. switch (cmd) {
  1440. case OPEN_CHANNEL:
  1441. rq = arg;
  1442. if (rq->protocol == ISDN_P_TE_S0)
  1443. err = open_dchannel_caller(isac, rq, __builtin_return_address(0));
  1444. else
  1445. err = open_bchannel(ipac, rq);
  1446. if (err)
  1447. break;
  1448. if (!try_module_get(ipac->owner))
  1449. pr_info("%s: cannot get module\n", ipac->name);
  1450. break;
  1451. case CLOSE_CHANNEL:
  1452. pr_debug("%s: dev(%d) close from %p\n", ipac->name,
  1453. dch->dev.id, __builtin_return_address(0));
  1454. module_put(ipac->owner);
  1455. break;
  1456. case CONTROL_CHANNEL:
  1457. err = channel_ctrl(ipac, arg);
  1458. break;
  1459. default:
  1460. pr_debug("%s: unknown DCTRL command %x\n", ipac->name, cmd);
  1461. return -EINVAL;
  1462. }
  1463. return err;
  1464. }
  1465. u32
  1466. mISDNipac_init(struct ipac_hw *ipac, void *hw)
  1467. {
  1468. u32 ret;
  1469. u8 i;
  1470. ipac->hw = hw;
  1471. if (ipac->isac.dch.debug & DEBUG_HW)
  1472. pr_notice("%s: ipac type %x\n", ipac->name, ipac->type);
  1473. if (ipac->type & IPAC_TYPE_HSCX) {
  1474. ipac->isac.type = IPAC_TYPE_ISAC;
  1475. ipac->hscx[0].off = 0;
  1476. ipac->hscx[1].off = 0x40;
  1477. ipac->hscx[0].fifo_size = 32;
  1478. ipac->hscx[1].fifo_size = 32;
  1479. } else if (ipac->type & IPAC_TYPE_IPAC) {
  1480. ipac->isac.type = IPAC_TYPE_IPAC | IPAC_TYPE_ISAC;
  1481. ipac->hscx[0].off = 0;
  1482. ipac->hscx[1].off = 0x40;
  1483. ipac->hscx[0].fifo_size = 64;
  1484. ipac->hscx[1].fifo_size = 64;
  1485. } else if (ipac->type & IPAC_TYPE_IPACX) {
  1486. ipac->isac.type = IPAC_TYPE_IPACX | IPAC_TYPE_ISACX;
  1487. ipac->hscx[0].off = IPACX_OFF_ICA;
  1488. ipac->hscx[1].off = IPACX_OFF_ICB;
  1489. ipac->hscx[0].fifo_size = 64;
  1490. ipac->hscx[1].fifo_size = 64;
  1491. } else
  1492. return 0;
  1493. mISDNisac_init(&ipac->isac, hw);
  1494. ipac->isac.dch.dev.D.ctrl = ipac_dctrl;
  1495. for (i = 0; i < 2; i++) {
  1496. ipac->hscx[i].bch.nr = i + 1;
  1497. set_channelmap(i + 1, ipac->isac.dch.dev.channelmap);
  1498. list_add(&ipac->hscx[i].bch.ch.list,
  1499. &ipac->isac.dch.dev.bchannels);
  1500. mISDN_initbchannel(&ipac->hscx[i].bch, MAX_DATA_MEM,
  1501. ipac->hscx[i].fifo_size);
  1502. ipac->hscx[i].bch.ch.nr = i + 1;
  1503. ipac->hscx[i].bch.ch.send = &hscx_l2l1;
  1504. ipac->hscx[i].bch.ch.ctrl = hscx_bctrl;
  1505. ipac->hscx[i].bch.hw = hw;
  1506. ipac->hscx[i].ip = ipac;
  1507. /* default values for IOM time slots
  1508. * can be overwritten by card */
  1509. ipac->hscx[i].slot = (i == 0) ? 0x2f : 0x03;
  1510. }
  1511. ipac->init = ipac_init;
  1512. ipac->release = free_ipac;
  1513. ret = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |
  1514. (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK));
  1515. return ret;
  1516. }
  1517. EXPORT_SYMBOL(mISDNipac_init);
  1518. static int __init
  1519. isac_mod_init(void)
  1520. {
  1521. pr_notice("mISDNipac module version %s\n", ISAC_REV);
  1522. return 0;
  1523. }
  1524. static void __exit
  1525. isac_mod_cleanup(void)
  1526. {
  1527. pr_notice("mISDNipac module unloaded\n");
  1528. }
  1529. module_init(isac_mod_init);
  1530. module_exit(isac_mod_cleanup);