amd7930_fn.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. /* gerdes_amd7930.c,v 0.99 2001/10/02
  2. *
  3. * gerdes_amd7930.c Amd 79C30A and 79C32A specific routines
  4. * (based on HiSax driver by Karsten Keil)
  5. *
  6. * Author Christoph Ersfeld <info@formula-n.de>
  7. * Formula-n Europe AG (www.formula-n.com)
  8. * previously Gerdes AG
  9. *
  10. *
  11. * This file is (c) under GNU PUBLIC LICENSE
  12. *
  13. *
  14. * Notes:
  15. * Version 0.99 is the first release of this driver and there are
  16. * certainly a few bugs.
  17. *
  18. * Please don't report any malfunction to me without sending
  19. * (compressed) debug-logs.
  20. * It would be nearly impossible to retrace it.
  21. *
  22. * Log D-channel-processing as follows:
  23. *
  24. * 1. Load hisax with card-specific parameters, this example ist for
  25. * Formula-n enter:now ISDN PCI and compatible
  26. * (f.e. Gerdes Power ISDN PCI)
  27. *
  28. * modprobe hisax type=41 protocol=2 id=gerdes
  29. *
  30. * if you chose an other value for id, you need to modify the
  31. * code below, too.
  32. *
  33. * 2. set debug-level
  34. *
  35. * hisaxctrl gerdes 1 0x3ff
  36. * hisaxctrl gerdes 11 0x4f
  37. * cat /dev/isdnctrl >> ~/log &
  38. *
  39. * Please take also a look into /var/log/messages if there is
  40. * anything importand concerning HISAX.
  41. *
  42. *
  43. * Credits:
  44. * Programming the driver for Formula-n enter:now ISDN PCI and
  45. * necessary this driver for the used Amd 7930 D-channel-controller
  46. * was spnsored by Formula-n Europe AG.
  47. * Thanks to Karsten Keil and Petr Novak, who gave me support in
  48. * Hisax-specific questions.
  49. * I want so say special thanks to Carl-Friedrich Braun, who had to
  50. * answer a lot of questions about generally ISDN and about handling
  51. * of the Amd-Chip.
  52. *
  53. */
  54. #include "hisax.h"
  55. #include "isdnl1.h"
  56. #include "isac.h"
  57. #include "amd7930_fn.h"
  58. #include <linux/interrupt.h>
  59. #include <linux/init.h>
  60. #include <linux/gfp.h>
  61. static void Amd7930_new_ph(struct IsdnCardState *cs);
  62. static WORD initAMD[] = {
  63. 0x0100,
  64. 0x00A5, 3, 0x01, 0x40, 0x58, // LPR, LMR1, LMR2
  65. 0x0086, 1, 0x0B, // DMR1 (D-Buffer TH-Interrupts on)
  66. 0x0087, 1, 0xFF, // DMR2
  67. 0x0092, 1, 0x03, // EFCR (extended mode d-channel-fifo on)
  68. 0x0090, 4, 0xFE, 0xFF, 0x02, 0x0F, // FRAR4, SRAR4, DMR3, DMR4 (address recognition )
  69. 0x0084, 2, 0x80, 0x00, // DRLR
  70. 0x00C0, 1, 0x47, // PPCR1
  71. 0x00C8, 1, 0x01, // PPCR2
  72. 0x0102,
  73. 0x0107,
  74. 0x01A1, 1,
  75. 0x0121, 1,
  76. 0x0189, 2,
  77. 0x0045, 4, 0x61, 0x72, 0x00, 0x00, // MCR1, MCR2, MCR3, MCR4
  78. 0x0063, 2, 0x08, 0x08, // GX
  79. 0x0064, 2, 0x08, 0x08, // GR
  80. 0x0065, 2, 0x99, 0x00, // GER
  81. 0x0066, 2, 0x7C, 0x8B, // STG
  82. 0x0067, 2, 0x00, 0x00, // FTGR1, FTGR2
  83. 0x0068, 2, 0x20, 0x20, // ATGR1, ATGR2
  84. 0x0069, 1, 0x4F, // MMR1
  85. 0x006A, 1, 0x00, // MMR2
  86. 0x006C, 1, 0x40, // MMR3
  87. 0x0021, 1, 0x02, // INIT
  88. 0x00A3, 1, 0x40, // LMR1
  89. 0xFFFF
  90. };
  91. static void /* macro wWordAMD */
  92. WriteWordAmd7930(struct IsdnCardState *cs, BYTE reg, WORD val)
  93. {
  94. wByteAMD(cs, 0x00, reg);
  95. wByteAMD(cs, 0x01, LOBYTE(val));
  96. wByteAMD(cs, 0x01, HIBYTE(val));
  97. }
  98. static WORD /* macro rWordAMD */
  99. ReadWordAmd7930(struct IsdnCardState *cs, BYTE reg)
  100. {
  101. WORD res;
  102. /* direct access register */
  103. if (reg < 8) {
  104. res = rByteAMD(cs, reg);
  105. res += 256 * rByteAMD(cs, reg);
  106. }
  107. /* indirect access register */
  108. else {
  109. wByteAMD(cs, 0x00, reg);
  110. res = rByteAMD(cs, 0x01);
  111. res += 256 * rByteAMD(cs, 0x01);
  112. }
  113. return (res);
  114. }
  115. static void
  116. Amd7930_ph_command(struct IsdnCardState *cs, u_char command, char *s)
  117. {
  118. if (cs->debug & L1_DEB_ISAC)
  119. debugl1(cs, "AMD7930: %s: ph_command 0x%02X", s, command);
  120. cs->dc.amd7930.lmr1 = command;
  121. wByteAMD(cs, 0xA3, command);
  122. }
  123. static BYTE i430States[] = {
  124. // to reset F3 F4 F5 F6 F7 F8 AR from
  125. 0x01, 0x02, 0x00, 0x00, 0x00, 0x07, 0x05, 0x00, // init
  126. 0x01, 0x02, 0x00, 0x00, 0x00, 0x07, 0x05, 0x00, // reset
  127. 0x01, 0x02, 0x00, 0x00, 0x00, 0x09, 0x05, 0x04, // F3
  128. 0x01, 0x02, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, // F4
  129. 0x01, 0x02, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, // F5
  130. 0x01, 0x03, 0x00, 0x00, 0x00, 0x06, 0x05, 0x00, // F6
  131. 0x11, 0x13, 0x00, 0x00, 0x1B, 0x00, 0x15, 0x00, // F7
  132. 0x01, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, // F8
  133. 0x01, 0x03, 0x00, 0x00, 0x00, 0x09, 0x00, 0x0A}; // AR
  134. /* Row init - reset F3 F4 F5 F6 F7 F8 AR */
  135. static BYTE stateHelper[] = { 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
  136. static void
  137. Amd7930_get_state(struct IsdnCardState *cs) {
  138. BYTE lsr = rByteAMD(cs, 0xA1);
  139. cs->dc.amd7930.ph_state = (lsr & 0x7) + 2;
  140. Amd7930_new_ph(cs);
  141. }
  142. static void
  143. Amd7930_new_ph(struct IsdnCardState *cs)
  144. {
  145. u_char index = stateHelper[cs->dc.amd7930.old_state] * 8 + stateHelper[cs->dc.amd7930.ph_state] - 1;
  146. u_char message = i430States[index];
  147. if (cs->debug & L1_DEB_ISAC)
  148. debugl1(cs, "AMD7930: new_ph %d, old_ph %d, message %d, index %d",
  149. cs->dc.amd7930.ph_state, cs->dc.amd7930.old_state, message & 0x0f, index);
  150. cs->dc.amd7930.old_state = cs->dc.amd7930.ph_state;
  151. /* abort transmit if nessesary */
  152. if ((message & 0xf0) && (cs->tx_skb)) {
  153. wByteAMD(cs, 0x21, 0xC2);
  154. wByteAMD(cs, 0x21, 0x02);
  155. }
  156. switch (message & 0x0f) {
  157. case (1):
  158. l1_msg(cs, HW_RESET | INDICATION, NULL);
  159. Amd7930_get_state(cs);
  160. break;
  161. case (2): /* init, Card starts in F3 */
  162. l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL);
  163. break;
  164. case (3):
  165. l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
  166. break;
  167. case (4):
  168. l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
  169. Amd7930_ph_command(cs, 0x50, "HW_ENABLE REQUEST");
  170. break;
  171. case (5):
  172. l1_msg(cs, HW_RSYNC | INDICATION, NULL);
  173. break;
  174. case (6):
  175. l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
  176. break;
  177. case (7): /* init, Card starts in F7 */
  178. l1_msg(cs, HW_RSYNC | INDICATION, NULL);
  179. l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
  180. break;
  181. case (8):
  182. l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
  183. /* fall through */
  184. case (9):
  185. Amd7930_ph_command(cs, 0x40, "HW_ENABLE REQ cleared if set");
  186. l1_msg(cs, HW_RSYNC | INDICATION, NULL);
  187. l1_msg(cs, HW_INFO2 | INDICATION, NULL);
  188. l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
  189. break;
  190. case (10):
  191. Amd7930_ph_command(cs, 0x40, "T3 expired, HW_ENABLE REQ cleared");
  192. cs->dc.amd7930.old_state = 3;
  193. break;
  194. case (11):
  195. l1_msg(cs, HW_INFO2 | INDICATION, NULL);
  196. break;
  197. default:
  198. break;
  199. }
  200. }
  201. static void
  202. Amd7930_bh(struct work_struct *work)
  203. {
  204. struct IsdnCardState *cs =
  205. container_of(work, struct IsdnCardState, tqueue);
  206. struct PStack *stptr;
  207. if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
  208. if (cs->debug)
  209. debugl1(cs, "Amd7930: bh, D-Channel Busy cleared");
  210. stptr = cs->stlist;
  211. while (stptr != NULL) {
  212. stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
  213. stptr = stptr->next;
  214. }
  215. }
  216. if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
  217. if (cs->debug & L1_DEB_ISAC)
  218. debugl1(cs, "AMD7930: bh, D_L1STATECHANGE");
  219. Amd7930_new_ph(cs);
  220. }
  221. if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) {
  222. if (cs->debug & L1_DEB_ISAC)
  223. debugl1(cs, "AMD7930: bh, D_RCVBUFREADY");
  224. DChannel_proc_rcv(cs);
  225. }
  226. if (test_and_clear_bit(D_XMTBUFREADY, &cs->event)) {
  227. if (cs->debug & L1_DEB_ISAC)
  228. debugl1(cs, "AMD7930: bh, D_XMTBUFREADY");
  229. DChannel_proc_xmt(cs);
  230. }
  231. }
  232. static void
  233. Amd7930_empty_Dfifo(struct IsdnCardState *cs, int flag)
  234. {
  235. BYTE stat, der;
  236. BYTE *ptr;
  237. struct sk_buff *skb;
  238. if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
  239. debugl1(cs, "Amd7930: empty_Dfifo");
  240. ptr = cs->rcvbuf + cs->rcvidx;
  241. /* AMD interrupts off */
  242. AmdIrqOff(cs);
  243. /* read D-Channel-Fifo*/
  244. stat = rByteAMD(cs, 0x07); // DSR2
  245. /* while Data in Fifo ... */
  246. while ((stat & 2) && ((ptr-cs->rcvbuf) < MAX_DFRAME_LEN_L1)) {
  247. *ptr = rByteAMD(cs, 0x04); // DCRB
  248. ptr++;
  249. stat = rByteAMD(cs, 0x07); // DSR2
  250. cs->rcvidx = ptr - cs->rcvbuf;
  251. /* Paket ready? */
  252. if (stat & 1) {
  253. der = rWordAMD(cs, 0x03);
  254. /* no errors, packet ok */
  255. if (!der && !flag) {
  256. rWordAMD(cs, 0x89); // clear DRCR
  257. if ((cs->rcvidx) > 0) {
  258. if (!(skb = alloc_skb(cs->rcvidx, GFP_ATOMIC)))
  259. printk(KERN_WARNING "HiSax: Amd7930: empty_Dfifo, D receive out of memory!\n");
  260. else {
  261. /* Debugging */
  262. if (cs->debug & L1_DEB_ISAC_FIFO) {
  263. char *t = cs->dlog;
  264. t += sprintf(t, "Amd7930: empty_Dfifo cnt: %d |", cs->rcvidx);
  265. QuickHex(t, cs->rcvbuf, cs->rcvidx);
  266. debugl1(cs, "%s", cs->dlog);
  267. }
  268. /* moves received data in sk-buffer */
  269. memcpy(skb_put(skb, cs->rcvidx), cs->rcvbuf, cs->rcvidx);
  270. skb_queue_tail(&cs->rq, skb);
  271. }
  272. }
  273. }
  274. /* throw damaged packets away, reset receive-buffer, indicate RX */
  275. ptr = cs->rcvbuf;
  276. cs->rcvidx = 0;
  277. schedule_event(cs, D_RCVBUFREADY);
  278. }
  279. }
  280. /* Packet to long, overflow */
  281. if (cs->rcvidx >= MAX_DFRAME_LEN_L1) {
  282. if (cs->debug & L1_DEB_WARN)
  283. debugl1(cs, "AMD7930: empty_Dfifo L2-Framelength overrun");
  284. cs->rcvidx = 0;
  285. return;
  286. }
  287. /* AMD interrupts on */
  288. AmdIrqOn(cs);
  289. }
  290. static void
  291. Amd7930_fill_Dfifo(struct IsdnCardState *cs)
  292. {
  293. WORD dtcrr, dtcrw, len, count;
  294. BYTE txstat, dmr3;
  295. BYTE *ptr, *deb_ptr;
  296. if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
  297. debugl1(cs, "Amd7930: fill_Dfifo");
  298. if ((!cs->tx_skb) || (cs->tx_skb->len <= 0))
  299. return;
  300. dtcrw = 0;
  301. if (!cs->dc.amd7930.tx_xmtlen)
  302. /* new Frame */
  303. len = dtcrw = cs->tx_skb->len;
  304. /* continue frame */
  305. else len = cs->dc.amd7930.tx_xmtlen;
  306. /* AMD interrupts off */
  307. AmdIrqOff(cs);
  308. deb_ptr = ptr = cs->tx_skb->data;
  309. /* while free place in tx-fifo available and data in sk-buffer */
  310. txstat = 0x10;
  311. while ((txstat & 0x10) && (cs->tx_cnt < len)) {
  312. wByteAMD(cs, 0x04, *ptr);
  313. ptr++;
  314. cs->tx_cnt++;
  315. txstat = rByteAMD(cs, 0x07);
  316. }
  317. count = ptr - cs->tx_skb->data;
  318. skb_pull(cs->tx_skb, count);
  319. dtcrr = rWordAMD(cs, 0x85); // DTCR
  320. dmr3 = rByteAMD(cs, 0x8E);
  321. if (cs->debug & L1_DEB_ISAC) {
  322. debugl1(cs, "Amd7930: fill_Dfifo, DMR3: 0x%02X, DTCR read: 0x%04X write: 0x%02X 0x%02X", dmr3, dtcrr, LOBYTE(dtcrw), HIBYTE(dtcrw));
  323. }
  324. /* writeing of dtcrw starts transmit */
  325. if (!cs->dc.amd7930.tx_xmtlen) {
  326. wWordAMD(cs, 0x85, dtcrw);
  327. cs->dc.amd7930.tx_xmtlen = dtcrw;
  328. }
  329. if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
  330. debugl1(cs, "Amd7930: fill_Dfifo dbusytimer running");
  331. del_timer(&cs->dbusytimer);
  332. }
  333. init_timer(&cs->dbusytimer);
  334. cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000);
  335. add_timer(&cs->dbusytimer);
  336. if (cs->debug & L1_DEB_ISAC_FIFO) {
  337. char *t = cs->dlog;
  338. t += sprintf(t, "Amd7930: fill_Dfifo cnt: %d |", count);
  339. QuickHex(t, deb_ptr, count);
  340. debugl1(cs, "%s", cs->dlog);
  341. }
  342. /* AMD interrupts on */
  343. AmdIrqOn(cs);
  344. }
  345. void Amd7930_interrupt(struct IsdnCardState *cs, BYTE irflags)
  346. {
  347. BYTE dsr1, dsr2, lsr;
  348. WORD der;
  349. while (irflags)
  350. {
  351. dsr1 = rByteAMD(cs, 0x02);
  352. der = rWordAMD(cs, 0x03);
  353. dsr2 = rByteAMD(cs, 0x07);
  354. lsr = rByteAMD(cs, 0xA1);
  355. if (cs->debug & L1_DEB_ISAC)
  356. debugl1(cs, "Amd7930: interrupt: flags: 0x%02X, DSR1: 0x%02X, DSR2: 0x%02X, LSR: 0x%02X, DER=0x%04X", irflags, dsr1, dsr2, lsr, der);
  357. /* D error -> read DER and DSR2 bit 2 */
  358. if (der || (dsr2 & 4)) {
  359. if (cs->debug & L1_DEB_WARN)
  360. debugl1(cs, "Amd7930: interrupt: D error DER=0x%04X", der);
  361. /* RX, TX abort if collision detected */
  362. if (der & 2) {
  363. wByteAMD(cs, 0x21, 0xC2);
  364. wByteAMD(cs, 0x21, 0x02);
  365. if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
  366. del_timer(&cs->dbusytimer);
  367. if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
  368. schedule_event(cs, D_CLEARBUSY);
  369. /* restart frame */
  370. if (cs->tx_skb) {
  371. skb_push(cs->tx_skb, cs->tx_cnt);
  372. cs->tx_cnt = 0;
  373. cs->dc.amd7930.tx_xmtlen = 0;
  374. Amd7930_fill_Dfifo(cs);
  375. } else {
  376. printk(KERN_WARNING "HiSax: Amd7930 D-Collision, no skb\n");
  377. debugl1(cs, "Amd7930: interrupt: D-Collision, no skb");
  378. }
  379. }
  380. /* remove damaged data from fifo */
  381. Amd7930_empty_Dfifo(cs, 1);
  382. if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
  383. del_timer(&cs->dbusytimer);
  384. if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
  385. schedule_event(cs, D_CLEARBUSY);
  386. /* restart TX-Frame */
  387. if (cs->tx_skb) {
  388. skb_push(cs->tx_skb, cs->tx_cnt);
  389. cs->tx_cnt = 0;
  390. cs->dc.amd7930.tx_xmtlen = 0;
  391. Amd7930_fill_Dfifo(cs);
  392. }
  393. }
  394. /* D TX FIFO empty -> fill */
  395. if (irflags & 1) {
  396. if (cs->debug & L1_DEB_ISAC)
  397. debugl1(cs, "Amd7930: interrupt: clear Timer and fill D-TX-FIFO if data");
  398. /* AMD interrupts off */
  399. AmdIrqOff(cs);
  400. if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
  401. del_timer(&cs->dbusytimer);
  402. if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
  403. schedule_event(cs, D_CLEARBUSY);
  404. if (cs->tx_skb) {
  405. if (cs->tx_skb->len)
  406. Amd7930_fill_Dfifo(cs);
  407. }
  408. /* AMD interrupts on */
  409. AmdIrqOn(cs);
  410. }
  411. /* D RX FIFO full or tiny packet in Fifo -> empty */
  412. if ((irflags & 2) || (dsr1 & 2)) {
  413. if (cs->debug & L1_DEB_ISAC)
  414. debugl1(cs, "Amd7930: interrupt: empty D-FIFO");
  415. Amd7930_empty_Dfifo(cs, 0);
  416. }
  417. /* D-Frame transmit complete */
  418. if (dsr1 & 64) {
  419. if (cs->debug & L1_DEB_ISAC) {
  420. debugl1(cs, "Amd7930: interrupt: transmit packet ready");
  421. }
  422. /* AMD interrupts off */
  423. AmdIrqOff(cs);
  424. if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
  425. del_timer(&cs->dbusytimer);
  426. if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
  427. schedule_event(cs, D_CLEARBUSY);
  428. if (cs->tx_skb) {
  429. if (cs->debug & L1_DEB_ISAC)
  430. debugl1(cs, "Amd7930: interrupt: TX-Packet ready, freeing skb");
  431. dev_kfree_skb_irq(cs->tx_skb);
  432. cs->tx_cnt = 0;
  433. cs->dc.amd7930.tx_xmtlen = 0;
  434. cs->tx_skb = NULL;
  435. }
  436. if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
  437. if (cs->debug & L1_DEB_ISAC)
  438. debugl1(cs, "Amd7930: interrupt: TX-Packet ready, next packet dequeued");
  439. cs->tx_cnt = 0;
  440. cs->dc.amd7930.tx_xmtlen = 0;
  441. Amd7930_fill_Dfifo(cs);
  442. }
  443. else
  444. schedule_event(cs, D_XMTBUFREADY);
  445. /* AMD interrupts on */
  446. AmdIrqOn(cs);
  447. }
  448. /* LIU status interrupt -> read LSR, check statechanges */
  449. if (lsr & 0x38) {
  450. /* AMD interrupts off */
  451. AmdIrqOff(cs);
  452. if (cs->debug & L1_DEB_ISAC)
  453. debugl1(cs, "Amd: interrupt: LSR=0x%02X, LIU is in state %d", lsr, ((lsr & 0x7) + 2));
  454. cs->dc.amd7930.ph_state = (lsr & 0x7) + 2;
  455. schedule_event(cs, D_L1STATECHANGE);
  456. /* AMD interrupts on */
  457. AmdIrqOn(cs);
  458. }
  459. /* reads Interrupt-Register again. If there is a new interrupt-flag: restart handler */
  460. irflags = rByteAMD(cs, 0x00);
  461. }
  462. }
  463. static void
  464. Amd7930_l1hw(struct PStack *st, int pr, void *arg)
  465. {
  466. struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
  467. struct sk_buff *skb = arg;
  468. u_long flags;
  469. if (cs->debug & L1_DEB_ISAC)
  470. debugl1(cs, "Amd7930: l1hw called, pr: 0x%04X", pr);
  471. switch (pr) {
  472. case (PH_DATA | REQUEST):
  473. if (cs->debug & DEB_DLOG_HEX)
  474. LogFrame(cs, skb->data, skb->len);
  475. if (cs->debug & DEB_DLOG_VERBOSE)
  476. dlogframe(cs, skb, 0);
  477. spin_lock_irqsave(&cs->lock, flags);
  478. if (cs->tx_skb) {
  479. skb_queue_tail(&cs->sq, skb);
  480. #ifdef L2FRAME_DEBUG /* psa */
  481. if (cs->debug & L1_DEB_LAPD)
  482. Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA Queued", 0);
  483. #endif
  484. } else {
  485. cs->tx_skb = skb;
  486. cs->tx_cnt = 0;
  487. cs->dc.amd7930.tx_xmtlen = 0;
  488. #ifdef L2FRAME_DEBUG /* psa */
  489. if (cs->debug & L1_DEB_LAPD)
  490. Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA", 0);
  491. #endif
  492. Amd7930_fill_Dfifo(cs);
  493. }
  494. spin_unlock_irqrestore(&cs->lock, flags);
  495. break;
  496. case (PH_PULL | INDICATION):
  497. spin_lock_irqsave(&cs->lock, flags);
  498. if (cs->tx_skb) {
  499. if (cs->debug & L1_DEB_WARN)
  500. debugl1(cs, "Amd7930: l1hw: l2l1 tx_skb exist this shouldn't happen");
  501. skb_queue_tail(&cs->sq, skb);
  502. spin_unlock_irqrestore(&cs->lock, flags);
  503. break;
  504. }
  505. if (cs->debug & DEB_DLOG_HEX)
  506. LogFrame(cs, skb->data, skb->len);
  507. if (cs->debug & DEB_DLOG_VERBOSE)
  508. dlogframe(cs, skb, 0);
  509. cs->tx_skb = skb;
  510. cs->tx_cnt = 0;
  511. cs->dc.amd7930.tx_xmtlen = 0;
  512. #ifdef L2FRAME_DEBUG /* psa */
  513. if (cs->debug & L1_DEB_LAPD)
  514. Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA_PULLED", 0);
  515. #endif
  516. Amd7930_fill_Dfifo(cs);
  517. spin_unlock_irqrestore(&cs->lock, flags);
  518. break;
  519. case (PH_PULL | REQUEST):
  520. #ifdef L2FRAME_DEBUG /* psa */
  521. if (cs->debug & L1_DEB_LAPD)
  522. debugl1(cs, "Amd7930: l1hw: -> PH_REQUEST_PULL, skb: %s", (cs->tx_skb) ? "yes" : "no");
  523. #endif
  524. if (!cs->tx_skb) {
  525. test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
  526. st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
  527. } else
  528. test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
  529. break;
  530. case (HW_RESET | REQUEST):
  531. spin_lock_irqsave(&cs->lock, flags);
  532. if ((cs->dc.amd7930.ph_state == 8)) {
  533. /* b-channels off, PH-AR cleared
  534. * change to F3 */
  535. Amd7930_ph_command(cs, 0x20, "HW_RESET REQUEST"); //LMR1 bit 5
  536. spin_unlock_irqrestore(&cs->lock, flags);
  537. } else {
  538. Amd7930_ph_command(cs, 0x40, "HW_RESET REQUEST");
  539. cs->dc.amd7930.ph_state = 2;
  540. spin_unlock_irqrestore(&cs->lock, flags);
  541. Amd7930_new_ph(cs);
  542. }
  543. break;
  544. case (HW_ENABLE | REQUEST):
  545. cs->dc.amd7930.ph_state = 9;
  546. Amd7930_new_ph(cs);
  547. break;
  548. case (HW_INFO3 | REQUEST):
  549. // automatic
  550. break;
  551. case (HW_TESTLOOP | REQUEST):
  552. /* not implemented yet */
  553. break;
  554. case (HW_DEACTIVATE | RESPONSE):
  555. skb_queue_purge(&cs->rq);
  556. skb_queue_purge(&cs->sq);
  557. if (cs->tx_skb) {
  558. dev_kfree_skb(cs->tx_skb);
  559. cs->tx_skb = NULL;
  560. }
  561. if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
  562. del_timer(&cs->dbusytimer);
  563. if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
  564. schedule_event(cs, D_CLEARBUSY);
  565. break;
  566. default:
  567. if (cs->debug & L1_DEB_WARN)
  568. debugl1(cs, "Amd7930: l1hw: unknown %04x", pr);
  569. break;
  570. }
  571. }
  572. static void
  573. setstack_Amd7930(struct PStack *st, struct IsdnCardState *cs)
  574. {
  575. if (cs->debug & L1_DEB_ISAC)
  576. debugl1(cs, "Amd7930: setstack called");
  577. st->l1.l1hw = Amd7930_l1hw;
  578. }
  579. static void
  580. DC_Close_Amd7930(struct IsdnCardState *cs) {
  581. if (cs->debug & L1_DEB_ISAC)
  582. debugl1(cs, "Amd7930: DC_Close called");
  583. }
  584. static void
  585. dbusy_timer_handler(struct IsdnCardState *cs)
  586. {
  587. u_long flags;
  588. struct PStack *stptr;
  589. WORD dtcr, der;
  590. BYTE dsr1, dsr2;
  591. if (cs->debug & L1_DEB_ISAC)
  592. debugl1(cs, "Amd7930: dbusy_timer expired!");
  593. if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
  594. spin_lock_irqsave(&cs->lock, flags);
  595. /* D Transmit Byte Count Register:
  596. * Counts down packet's number of Bytes, 0 if packet ready */
  597. dtcr = rWordAMD(cs, 0x85);
  598. dsr1 = rByteAMD(cs, 0x02);
  599. dsr2 = rByteAMD(cs, 0x07);
  600. der = rWordAMD(cs, 0x03);
  601. if (cs->debug & L1_DEB_ISAC)
  602. debugl1(cs, "Amd7930: dbusy_timer_handler: DSR1=0x%02X, DSR2=0x%02X, DER=0x%04X, cs->tx_skb->len=%u, tx_stat=%u, dtcr=%u, cs->tx_cnt=%u", dsr1, dsr2, der, cs->tx_skb->len, cs->dc.amd7930.tx_xmtlen, dtcr, cs->tx_cnt);
  603. if ((cs->dc.amd7930.tx_xmtlen - dtcr) < cs->tx_cnt) { /* D-Channel Busy */
  604. test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
  605. stptr = cs->stlist;
  606. spin_unlock_irqrestore(&cs->lock, flags);
  607. while (stptr != NULL) {
  608. stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
  609. stptr = stptr->next;
  610. }
  611. } else {
  612. /* discard frame; reset transceiver */
  613. test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags);
  614. if (cs->tx_skb) {
  615. dev_kfree_skb_any(cs->tx_skb);
  616. cs->tx_cnt = 0;
  617. cs->tx_skb = NULL;
  618. cs->dc.amd7930.tx_xmtlen = 0;
  619. } else {
  620. printk(KERN_WARNING "HiSax: Amd7930: D-Channel Busy no skb\n");
  621. debugl1(cs, "Amd7930: D-Channel Busy no skb");
  622. }
  623. /* Transmitter reset, abort transmit */
  624. wByteAMD(cs, 0x21, 0x82);
  625. wByteAMD(cs, 0x21, 0x02);
  626. spin_unlock_irqrestore(&cs->lock, flags);
  627. cs->irq_func(cs->irq, cs);
  628. if (cs->debug & L1_DEB_ISAC)
  629. debugl1(cs, "Amd7930: dbusy_timer_handler: Transmitter reset");
  630. }
  631. }
  632. }
  633. void Amd7930_init(struct IsdnCardState *cs)
  634. {
  635. WORD *ptr;
  636. BYTE cmd, cnt;
  637. if (cs->debug & L1_DEB_ISAC)
  638. debugl1(cs, "Amd7930: initamd called");
  639. cs->dc.amd7930.tx_xmtlen = 0;
  640. cs->dc.amd7930.old_state = 0;
  641. cs->dc.amd7930.lmr1 = 0x40;
  642. cs->dc.amd7930.ph_command = Amd7930_ph_command;
  643. cs->setstack_d = setstack_Amd7930;
  644. cs->DC_Close = DC_Close_Amd7930;
  645. /* AMD Initialisation */
  646. for (ptr = initAMD; *ptr != 0xFFFF; ) {
  647. cmd = LOBYTE(*ptr);
  648. /* read */
  649. if (*ptr++ >= 0x100) {
  650. if (cmd < 8)
  651. /* reset register */
  652. rByteAMD(cs, cmd);
  653. else {
  654. wByteAMD(cs, 0x00, cmd);
  655. for (cnt = *ptr++; cnt > 0; cnt--)
  656. rByteAMD(cs, 0x01);
  657. }
  658. }
  659. /* write */
  660. else if (cmd < 8)
  661. wByteAMD(cs, cmd, LOBYTE(*ptr++));
  662. else {
  663. wByteAMD(cs, 0x00, cmd);
  664. for (cnt = *ptr++; cnt > 0; cnt--)
  665. wByteAMD(cs, 0x01, LOBYTE(*ptr++));
  666. }
  667. }
  668. }
  669. void setup_Amd7930(struct IsdnCardState *cs)
  670. {
  671. INIT_WORK(&cs->tqueue, Amd7930_bh);
  672. cs->dbusytimer.function = (void *) dbusy_timer_handler;
  673. cs->dbusytimer.data = (long) cs;
  674. init_timer(&cs->dbusytimer);
  675. }