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