amd7930_fn.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795
  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. skb_put_data(skb, cs->rcvbuf,
  270. cs->rcvidx);
  271. skb_queue_tail(&cs->rq, skb);
  272. }
  273. }
  274. }
  275. /* throw damaged packets away, reset receive-buffer, indicate RX */
  276. ptr = cs->rcvbuf;
  277. cs->rcvidx = 0;
  278. schedule_event(cs, D_RCVBUFREADY);
  279. }
  280. }
  281. /* Packet to long, overflow */
  282. if (cs->rcvidx >= MAX_DFRAME_LEN_L1) {
  283. if (cs->debug & L1_DEB_WARN)
  284. debugl1(cs, "AMD7930: empty_Dfifo L2-Framelength overrun");
  285. cs->rcvidx = 0;
  286. return;
  287. }
  288. /* AMD interrupts on */
  289. AmdIrqOn(cs);
  290. }
  291. static void
  292. Amd7930_fill_Dfifo(struct IsdnCardState *cs)
  293. {
  294. WORD dtcrr, dtcrw, len, count;
  295. BYTE txstat, dmr3;
  296. BYTE *ptr, *deb_ptr;
  297. if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
  298. debugl1(cs, "Amd7930: fill_Dfifo");
  299. if ((!cs->tx_skb) || (cs->tx_skb->len <= 0))
  300. return;
  301. dtcrw = 0;
  302. if (!cs->dc.amd7930.tx_xmtlen)
  303. /* new Frame */
  304. len = dtcrw = cs->tx_skb->len;
  305. /* continue frame */
  306. else len = cs->dc.amd7930.tx_xmtlen;
  307. /* AMD interrupts off */
  308. AmdIrqOff(cs);
  309. deb_ptr = ptr = cs->tx_skb->data;
  310. /* while free place in tx-fifo available and data in sk-buffer */
  311. txstat = 0x10;
  312. while ((txstat & 0x10) && (cs->tx_cnt < len)) {
  313. wByteAMD(cs, 0x04, *ptr);
  314. ptr++;
  315. cs->tx_cnt++;
  316. txstat = rByteAMD(cs, 0x07);
  317. }
  318. count = ptr - cs->tx_skb->data;
  319. skb_pull(cs->tx_skb, count);
  320. dtcrr = rWordAMD(cs, 0x85); // DTCR
  321. dmr3 = rByteAMD(cs, 0x8E);
  322. if (cs->debug & L1_DEB_ISAC) {
  323. debugl1(cs, "Amd7930: fill_Dfifo, DMR3: 0x%02X, DTCR read: 0x%04X write: 0x%02X 0x%02X", dmr3, dtcrr, LOBYTE(dtcrw), HIBYTE(dtcrw));
  324. }
  325. /* writeing of dtcrw starts transmit */
  326. if (!cs->dc.amd7930.tx_xmtlen) {
  327. wWordAMD(cs, 0x85, dtcrw);
  328. cs->dc.amd7930.tx_xmtlen = dtcrw;
  329. }
  330. if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
  331. debugl1(cs, "Amd7930: fill_Dfifo dbusytimer running");
  332. del_timer(&cs->dbusytimer);
  333. }
  334. init_timer(&cs->dbusytimer);
  335. cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000);
  336. add_timer(&cs->dbusytimer);
  337. if (cs->debug & L1_DEB_ISAC_FIFO) {
  338. char *t = cs->dlog;
  339. t += sprintf(t, "Amd7930: fill_Dfifo cnt: %d |", count);
  340. QuickHex(t, deb_ptr, count);
  341. debugl1(cs, "%s", cs->dlog);
  342. }
  343. /* AMD interrupts on */
  344. AmdIrqOn(cs);
  345. }
  346. void Amd7930_interrupt(struct IsdnCardState *cs, BYTE irflags)
  347. {
  348. BYTE dsr1, dsr2, lsr;
  349. WORD der;
  350. while (irflags)
  351. {
  352. dsr1 = rByteAMD(cs, 0x02);
  353. der = rWordAMD(cs, 0x03);
  354. dsr2 = rByteAMD(cs, 0x07);
  355. lsr = rByteAMD(cs, 0xA1);
  356. if (cs->debug & L1_DEB_ISAC)
  357. debugl1(cs, "Amd7930: interrupt: flags: 0x%02X, DSR1: 0x%02X, DSR2: 0x%02X, LSR: 0x%02X, DER=0x%04X", irflags, dsr1, dsr2, lsr, der);
  358. /* D error -> read DER and DSR2 bit 2 */
  359. if (der || (dsr2 & 4)) {
  360. if (cs->debug & L1_DEB_WARN)
  361. debugl1(cs, "Amd7930: interrupt: D error DER=0x%04X", der);
  362. /* RX, TX abort if collision detected */
  363. if (der & 2) {
  364. wByteAMD(cs, 0x21, 0xC2);
  365. wByteAMD(cs, 0x21, 0x02);
  366. if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
  367. del_timer(&cs->dbusytimer);
  368. if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
  369. schedule_event(cs, D_CLEARBUSY);
  370. /* restart frame */
  371. if (cs->tx_skb) {
  372. skb_push(cs->tx_skb, cs->tx_cnt);
  373. cs->tx_cnt = 0;
  374. cs->dc.amd7930.tx_xmtlen = 0;
  375. Amd7930_fill_Dfifo(cs);
  376. } else {
  377. printk(KERN_WARNING "HiSax: Amd7930 D-Collision, no skb\n");
  378. debugl1(cs, "Amd7930: interrupt: D-Collision, no skb");
  379. }
  380. }
  381. /* remove damaged data from fifo */
  382. Amd7930_empty_Dfifo(cs, 1);
  383. if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
  384. del_timer(&cs->dbusytimer);
  385. if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
  386. schedule_event(cs, D_CLEARBUSY);
  387. /* restart TX-Frame */
  388. if (cs->tx_skb) {
  389. skb_push(cs->tx_skb, cs->tx_cnt);
  390. cs->tx_cnt = 0;
  391. cs->dc.amd7930.tx_xmtlen = 0;
  392. Amd7930_fill_Dfifo(cs);
  393. }
  394. }
  395. /* D TX FIFO empty -> fill */
  396. if (irflags & 1) {
  397. if (cs->debug & L1_DEB_ISAC)
  398. debugl1(cs, "Amd7930: interrupt: clear Timer and fill D-TX-FIFO if data");
  399. /* AMD interrupts off */
  400. AmdIrqOff(cs);
  401. if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
  402. del_timer(&cs->dbusytimer);
  403. if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
  404. schedule_event(cs, D_CLEARBUSY);
  405. if (cs->tx_skb) {
  406. if (cs->tx_skb->len)
  407. Amd7930_fill_Dfifo(cs);
  408. }
  409. /* AMD interrupts on */
  410. AmdIrqOn(cs);
  411. }
  412. /* D RX FIFO full or tiny packet in Fifo -> empty */
  413. if ((irflags & 2) || (dsr1 & 2)) {
  414. if (cs->debug & L1_DEB_ISAC)
  415. debugl1(cs, "Amd7930: interrupt: empty D-FIFO");
  416. Amd7930_empty_Dfifo(cs, 0);
  417. }
  418. /* D-Frame transmit complete */
  419. if (dsr1 & 64) {
  420. if (cs->debug & L1_DEB_ISAC) {
  421. debugl1(cs, "Amd7930: interrupt: transmit packet ready");
  422. }
  423. /* AMD interrupts off */
  424. AmdIrqOff(cs);
  425. if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
  426. del_timer(&cs->dbusytimer);
  427. if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
  428. schedule_event(cs, D_CLEARBUSY);
  429. if (cs->tx_skb) {
  430. if (cs->debug & L1_DEB_ISAC)
  431. debugl1(cs, "Amd7930: interrupt: TX-Packet ready, freeing skb");
  432. dev_kfree_skb_irq(cs->tx_skb);
  433. cs->tx_cnt = 0;
  434. cs->dc.amd7930.tx_xmtlen = 0;
  435. cs->tx_skb = NULL;
  436. }
  437. if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
  438. if (cs->debug & L1_DEB_ISAC)
  439. debugl1(cs, "Amd7930: interrupt: TX-Packet ready, next packet dequeued");
  440. cs->tx_cnt = 0;
  441. cs->dc.amd7930.tx_xmtlen = 0;
  442. Amd7930_fill_Dfifo(cs);
  443. }
  444. else
  445. schedule_event(cs, D_XMTBUFREADY);
  446. /* AMD interrupts on */
  447. AmdIrqOn(cs);
  448. }
  449. /* LIU status interrupt -> read LSR, check statechanges */
  450. if (lsr & 0x38) {
  451. /* AMD interrupts off */
  452. AmdIrqOff(cs);
  453. if (cs->debug & L1_DEB_ISAC)
  454. debugl1(cs, "Amd: interrupt: LSR=0x%02X, LIU is in state %d", lsr, ((lsr & 0x7) + 2));
  455. cs->dc.amd7930.ph_state = (lsr & 0x7) + 2;
  456. schedule_event(cs, D_L1STATECHANGE);
  457. /* AMD interrupts on */
  458. AmdIrqOn(cs);
  459. }
  460. /* reads Interrupt-Register again. If there is a new interrupt-flag: restart handler */
  461. irflags = rByteAMD(cs, 0x00);
  462. }
  463. }
  464. static void
  465. Amd7930_l1hw(struct PStack *st, int pr, void *arg)
  466. {
  467. struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
  468. struct sk_buff *skb = arg;
  469. u_long flags;
  470. if (cs->debug & L1_DEB_ISAC)
  471. debugl1(cs, "Amd7930: l1hw called, pr: 0x%04X", pr);
  472. switch (pr) {
  473. case (PH_DATA | REQUEST):
  474. if (cs->debug & DEB_DLOG_HEX)
  475. LogFrame(cs, skb->data, skb->len);
  476. if (cs->debug & DEB_DLOG_VERBOSE)
  477. dlogframe(cs, skb, 0);
  478. spin_lock_irqsave(&cs->lock, flags);
  479. if (cs->tx_skb) {
  480. skb_queue_tail(&cs->sq, skb);
  481. #ifdef L2FRAME_DEBUG /* psa */
  482. if (cs->debug & L1_DEB_LAPD)
  483. Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA Queued", 0);
  484. #endif
  485. } else {
  486. cs->tx_skb = skb;
  487. cs->tx_cnt = 0;
  488. cs->dc.amd7930.tx_xmtlen = 0;
  489. #ifdef L2FRAME_DEBUG /* psa */
  490. if (cs->debug & L1_DEB_LAPD)
  491. Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA", 0);
  492. #endif
  493. Amd7930_fill_Dfifo(cs);
  494. }
  495. spin_unlock_irqrestore(&cs->lock, flags);
  496. break;
  497. case (PH_PULL | INDICATION):
  498. spin_lock_irqsave(&cs->lock, flags);
  499. if (cs->tx_skb) {
  500. if (cs->debug & L1_DEB_WARN)
  501. debugl1(cs, "Amd7930: l1hw: l2l1 tx_skb exist this shouldn't happen");
  502. skb_queue_tail(&cs->sq, skb);
  503. spin_unlock_irqrestore(&cs->lock, flags);
  504. break;
  505. }
  506. if (cs->debug & DEB_DLOG_HEX)
  507. LogFrame(cs, skb->data, skb->len);
  508. if (cs->debug & DEB_DLOG_VERBOSE)
  509. dlogframe(cs, skb, 0);
  510. cs->tx_skb = skb;
  511. cs->tx_cnt = 0;
  512. cs->dc.amd7930.tx_xmtlen = 0;
  513. #ifdef L2FRAME_DEBUG /* psa */
  514. if (cs->debug & L1_DEB_LAPD)
  515. Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA_PULLED", 0);
  516. #endif
  517. Amd7930_fill_Dfifo(cs);
  518. spin_unlock_irqrestore(&cs->lock, flags);
  519. break;
  520. case (PH_PULL | REQUEST):
  521. #ifdef L2FRAME_DEBUG /* psa */
  522. if (cs->debug & L1_DEB_LAPD)
  523. debugl1(cs, "Amd7930: l1hw: -> PH_REQUEST_PULL, skb: %s", (cs->tx_skb) ? "yes" : "no");
  524. #endif
  525. if (!cs->tx_skb) {
  526. test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
  527. st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
  528. } else
  529. test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
  530. break;
  531. case (HW_RESET | REQUEST):
  532. spin_lock_irqsave(&cs->lock, flags);
  533. if ((cs->dc.amd7930.ph_state == 8)) {
  534. /* b-channels off, PH-AR cleared
  535. * change to F3 */
  536. Amd7930_ph_command(cs, 0x20, "HW_RESET REQUEST"); //LMR1 bit 5
  537. spin_unlock_irqrestore(&cs->lock, flags);
  538. } else {
  539. Amd7930_ph_command(cs, 0x40, "HW_RESET REQUEST");
  540. cs->dc.amd7930.ph_state = 2;
  541. spin_unlock_irqrestore(&cs->lock, flags);
  542. Amd7930_new_ph(cs);
  543. }
  544. break;
  545. case (HW_ENABLE | REQUEST):
  546. cs->dc.amd7930.ph_state = 9;
  547. Amd7930_new_ph(cs);
  548. break;
  549. case (HW_INFO3 | REQUEST):
  550. // automatic
  551. break;
  552. case (HW_TESTLOOP | REQUEST):
  553. /* not implemented yet */
  554. break;
  555. case (HW_DEACTIVATE | RESPONSE):
  556. skb_queue_purge(&cs->rq);
  557. skb_queue_purge(&cs->sq);
  558. if (cs->tx_skb) {
  559. dev_kfree_skb(cs->tx_skb);
  560. cs->tx_skb = NULL;
  561. }
  562. if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
  563. del_timer(&cs->dbusytimer);
  564. if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
  565. schedule_event(cs, D_CLEARBUSY);
  566. break;
  567. default:
  568. if (cs->debug & L1_DEB_WARN)
  569. debugl1(cs, "Amd7930: l1hw: unknown %04x", pr);
  570. break;
  571. }
  572. }
  573. static void
  574. setstack_Amd7930(struct PStack *st, struct IsdnCardState *cs)
  575. {
  576. if (cs->debug & L1_DEB_ISAC)
  577. debugl1(cs, "Amd7930: setstack called");
  578. st->l1.l1hw = Amd7930_l1hw;
  579. }
  580. static void
  581. DC_Close_Amd7930(struct IsdnCardState *cs) {
  582. if (cs->debug & L1_DEB_ISAC)
  583. debugl1(cs, "Amd7930: DC_Close called");
  584. }
  585. static void
  586. dbusy_timer_handler(struct IsdnCardState *cs)
  587. {
  588. u_long flags;
  589. struct PStack *stptr;
  590. WORD dtcr, der;
  591. BYTE dsr1, dsr2;
  592. if (cs->debug & L1_DEB_ISAC)
  593. debugl1(cs, "Amd7930: dbusy_timer expired!");
  594. if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
  595. spin_lock_irqsave(&cs->lock, flags);
  596. /* D Transmit Byte Count Register:
  597. * Counts down packet's number of Bytes, 0 if packet ready */
  598. dtcr = rWordAMD(cs, 0x85);
  599. dsr1 = rByteAMD(cs, 0x02);
  600. dsr2 = rByteAMD(cs, 0x07);
  601. der = rWordAMD(cs, 0x03);
  602. if (cs->debug & L1_DEB_ISAC)
  603. 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);
  604. if ((cs->dc.amd7930.tx_xmtlen - dtcr) < cs->tx_cnt) { /* D-Channel Busy */
  605. test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
  606. stptr = cs->stlist;
  607. spin_unlock_irqrestore(&cs->lock, flags);
  608. while (stptr != NULL) {
  609. stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
  610. stptr = stptr->next;
  611. }
  612. } else {
  613. /* discard frame; reset transceiver */
  614. test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags);
  615. if (cs->tx_skb) {
  616. dev_kfree_skb_any(cs->tx_skb);
  617. cs->tx_cnt = 0;
  618. cs->tx_skb = NULL;
  619. cs->dc.amd7930.tx_xmtlen = 0;
  620. } else {
  621. printk(KERN_WARNING "HiSax: Amd7930: D-Channel Busy no skb\n");
  622. debugl1(cs, "Amd7930: D-Channel Busy no skb");
  623. }
  624. /* Transmitter reset, abort transmit */
  625. wByteAMD(cs, 0x21, 0x82);
  626. wByteAMD(cs, 0x21, 0x02);
  627. spin_unlock_irqrestore(&cs->lock, flags);
  628. cs->irq_func(cs->irq, cs);
  629. if (cs->debug & L1_DEB_ISAC)
  630. debugl1(cs, "Amd7930: dbusy_timer_handler: Transmitter reset");
  631. }
  632. }
  633. }
  634. void Amd7930_init(struct IsdnCardState *cs)
  635. {
  636. WORD *ptr;
  637. BYTE cmd, cnt;
  638. if (cs->debug & L1_DEB_ISAC)
  639. debugl1(cs, "Amd7930: initamd called");
  640. cs->dc.amd7930.tx_xmtlen = 0;
  641. cs->dc.amd7930.old_state = 0;
  642. cs->dc.amd7930.lmr1 = 0x40;
  643. cs->dc.amd7930.ph_command = Amd7930_ph_command;
  644. cs->setstack_d = setstack_Amd7930;
  645. cs->DC_Close = DC_Close_Amd7930;
  646. /* AMD Initialisation */
  647. for (ptr = initAMD; *ptr != 0xFFFF; ) {
  648. cmd = LOBYTE(*ptr);
  649. /* read */
  650. if (*ptr++ >= 0x100) {
  651. if (cmd < 8)
  652. /* reset register */
  653. rByteAMD(cs, cmd);
  654. else {
  655. wByteAMD(cs, 0x00, cmd);
  656. for (cnt = *ptr++; cnt > 0; cnt--)
  657. rByteAMD(cs, 0x01);
  658. }
  659. }
  660. /* write */
  661. else if (cmd < 8)
  662. wByteAMD(cs, cmd, LOBYTE(*ptr++));
  663. else {
  664. wByteAMD(cs, 0x00, cmd);
  665. for (cnt = *ptr++; cnt > 0; cnt--)
  666. wByteAMD(cs, 0x01, LOBYTE(*ptr++));
  667. }
  668. }
  669. }
  670. void setup_Amd7930(struct IsdnCardState *cs)
  671. {
  672. INIT_WORK(&cs->tqueue, Amd7930_bh);
  673. setup_timer(&cs->dbusytimer, (void *)dbusy_timer_handler, (long)cs);
  674. }