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 work_struct *work)
  202. {
  203. struct IsdnCardState *cs =
  204. container_of(work, struct IsdnCardState, tqueue);
  205. struct PStack *stptr;
  206. if (!cs)
  207. return;
  208. if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
  209. if (cs->debug)
  210. debugl1(cs, "Amd7930: bh, D-Channel Busy cleared");
  211. stptr = cs->stlist;
  212. while (stptr != NULL) {
  213. stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
  214. stptr = stptr->next;
  215. }
  216. }
  217. if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
  218. if (cs->debug & L1_DEB_ISAC)
  219. debugl1(cs, "AMD7930: bh, D_L1STATECHANGE");
  220. Amd7930_new_ph(cs);
  221. }
  222. if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) {
  223. if (cs->debug & L1_DEB_ISAC)
  224. debugl1(cs, "AMD7930: bh, D_RCVBUFREADY");
  225. DChannel_proc_rcv(cs);
  226. }
  227. if (test_and_clear_bit(D_XMTBUFREADY, &cs->event)) {
  228. if (cs->debug & L1_DEB_ISAC)
  229. debugl1(cs, "AMD7930: bh, D_XMTBUFREADY");
  230. DChannel_proc_xmt(cs);
  231. }
  232. }
  233. static void
  234. Amd7930_empty_Dfifo(struct IsdnCardState *cs, int flag)
  235. {
  236. BYTE stat, der;
  237. BYTE *ptr;
  238. struct sk_buff *skb;
  239. if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
  240. debugl1(cs, "Amd7930: empty_Dfifo");
  241. ptr = cs->rcvbuf + cs->rcvidx;
  242. /* AMD interrupts off */
  243. AmdIrqOff(cs);
  244. /* read D-Channel-Fifo*/
  245. stat = rByteAMD(cs, 0x07); // DSR2
  246. /* while Data in Fifo ... */
  247. while ( (stat & 2) && ((ptr-cs->rcvbuf) < MAX_DFRAME_LEN_L1) ) {
  248. *ptr = rByteAMD(cs, 0x04); // DCRB
  249. ptr++;
  250. stat = rByteAMD(cs, 0x07); // DSR2
  251. cs->rcvidx = ptr - cs->rcvbuf;
  252. /* Paket ready? */
  253. if (stat & 1) {
  254. der = rWordAMD(cs, 0x03);
  255. /* no errors, packet ok */
  256. if(!der && !flag) {
  257. rWordAMD(cs, 0x89); // clear DRCR
  258. if ((cs->rcvidx) > 0) {
  259. if (!(skb = alloc_skb(cs->rcvidx, GFP_ATOMIC)))
  260. printk(KERN_WARNING "HiSax: Amd7930: empty_Dfifo, D receive out of memory!\n");
  261. else {
  262. /* Debugging */
  263. if (cs->debug & L1_DEB_ISAC_FIFO) {
  264. char *t = cs->dlog;
  265. t += sprintf(t, "Amd7930: empty_Dfifo cnt: %d |", cs->rcvidx);
  266. QuickHex(t, cs->rcvbuf, cs->rcvidx);
  267. debugl1(cs, cs->dlog);
  268. }
  269. /* moves received data in sk-buffer */
  270. memcpy(skb_put(skb, cs->rcvidx), cs->rcvbuf, 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, 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. 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 REQEST"); //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 __devinit
  670. setup_Amd7930(struct IsdnCardState *cs)
  671. {
  672. INIT_WORK(&cs->tqueue, Amd7930_bh);
  673. cs->dbusytimer.function = (void *) dbusy_timer_handler;
  674. cs->dbusytimer.data = (long) cs;
  675. init_timer(&cs->dbusytimer);
  676. }