smdma.h
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*****************************************************************************/
  2. /*
  3.  * smdma.h  --  soundcard radio modem driver dma buffer routines.
  4.  *
  5.  * Copyright (C) 1996  Thomas Sailer (sailer@ife.ee.ethz.ch)
  6.  *
  7.  * This program is free software; you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation; either version 2 of the License, or
  10.  * (at your option) any later version.
  11.  *
  12.  * This program is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program; if not, write to the Free Software
  19.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  *
  21.  *  Please note that the GPL allows you to use the driver, NOT the radio.
  22.  *  In order to use the radio, you need a license from the communications
  23.  *  authority of your country.
  24.  *
  25.  */
  26. #ifndef _SMDMA_H
  27. #define _SMDMA_H
  28. /* ---------------------------------------------------------------------- */
  29. #include "sm.h"
  30. /* ---------------------------------------------------------------------- */
  31. #define DMA_MODE_AUTOINIT      0x10
  32. #define NUM_FRAGMENTS          4
  33. /*
  34.  * NOTE: make sure that hdlcdrv_hdlcbuffer contains enough space
  35.  * for the modulator to fill the whole DMA buffer without underrun
  36.  * at the highest possible baud rate, otherwise the TX state machine will
  37.  * not work correctly. That is (9k6 FSK): HDLCDRV_HDLCBUFFER > 6*NUM_FRAGMENTS
  38.  */ 
  39. /* --------------------------------------------------------------------- */
  40. /*
  41.  * ===================== DMA buffer management ===========================
  42.  */
  43. /*
  44.  * returns the number of samples per fragment
  45.  */
  46. static inline unsigned int dma_setup(struct sm_state *sm, int send, unsigned int dmanr)
  47. {
  48. if (send) {
  49. disable_dma(dmanr);
  50. clear_dma_ff(dmanr);
  51. set_dma_mode(dmanr, DMA_MODE_WRITE | DMA_MODE_AUTOINIT);
  52. set_dma_addr(dmanr, virt_to_bus(sm->dma.obuf));
  53. set_dma_count(dmanr, sm->dma.ofragsz * NUM_FRAGMENTS);
  54. enable_dma(dmanr);
  55. if (sm->dma.o16bit)
  56. return sm->dma.ofragsz/2;
  57. return sm->dma.ofragsz;
  58. } else {
  59. disable_dma(dmanr);
  60. clear_dma_ff(dmanr);
  61. set_dma_mode(dmanr, DMA_MODE_READ | DMA_MODE_AUTOINIT);
  62. set_dma_addr(dmanr, virt_to_bus(sm->dma.ibuf));
  63. set_dma_count(dmanr, sm->dma.ifragsz * NUM_FRAGMENTS);
  64. enable_dma(dmanr);
  65. if (sm->dma.i16bit)
  66. return sm->dma.ifragsz/2;
  67. return sm->dma.ifragsz;
  68. }
  69. }
  70. /* --------------------------------------------------------------------- */
  71. static inline unsigned int dma_ptr(struct sm_state *sm, int send, unsigned int dmanr,
  72.        unsigned int *curfrag)
  73. {
  74. unsigned int dmaptr, sz, frg, offs;
  75. dmaptr = get_dma_residue(dmanr);
  76. if (send) {
  77. sz = sm->dma.ofragsz * NUM_FRAGMENTS;
  78. if (dmaptr == 0 || dmaptr > sz)
  79. dmaptr = sz;
  80. dmaptr--;
  81. frg = dmaptr / sm->dma.ofragsz;
  82. offs = (dmaptr % sm->dma.ofragsz) + 1;
  83. *curfrag = NUM_FRAGMENTS - 1 - frg;
  84. #ifdef SM_DEBUG
  85. if (!sm->debug_vals.dma_residue || offs < sm->debug_vals.dma_residue)
  86. sm->debug_vals.dma_residue = offs;
  87. #endif /* SM_DEBUG */
  88. if (sm->dma.o16bit)
  89. return offs/2;
  90. return offs;
  91. } else {
  92. sz = sm->dma.ifragsz * NUM_FRAGMENTS;
  93. if (dmaptr == 0 || dmaptr > sz)
  94. dmaptr = sz;
  95. dmaptr--;
  96. frg = dmaptr / sm->dma.ifragsz;
  97. offs = (dmaptr % sm->dma.ifragsz) + 1;
  98. *curfrag = NUM_FRAGMENTS - 1 - frg;
  99. #ifdef SM_DEBUG
  100. if (!sm->debug_vals.dma_residue || offs < sm->debug_vals.dma_residue)
  101. sm->debug_vals.dma_residue = offs;
  102. #endif /* SM_DEBUG */
  103. if (sm->dma.i16bit)
  104. return offs/2;
  105. return offs;
  106. }
  107. }
  108. /* --------------------------------------------------------------------- */
  109. static inline int dma_end_transmit(struct sm_state *sm, unsigned int curfrag)
  110. {
  111. unsigned int diff = (NUM_FRAGMENTS + curfrag - sm->dma.ofragptr) % NUM_FRAGMENTS;
  112. sm->dma.ofragptr = curfrag;
  113. if (sm->dma.ptt_cnt <= 0) {
  114. sm->dma.ptt_cnt = 0;
  115. return 0;
  116. }
  117. sm->dma.ptt_cnt -= diff;
  118. if (sm->dma.ptt_cnt <= 0) {
  119. sm->dma.ptt_cnt = 0;
  120. return -1;
  121. }
  122. return 0;
  123. }
  124. static inline void dma_transmit(struct sm_state *sm)
  125. {
  126. void *p;
  127. while (sm->dma.ptt_cnt < NUM_FRAGMENTS && hdlcdrv_ptt(&sm->hdrv)) {
  128. p = (unsigned char *)sm->dma.obuf + sm->dma.ofragsz *
  129. ((sm->dma.ofragptr + sm->dma.ptt_cnt) % NUM_FRAGMENTS);
  130. if (sm->dma.o16bit) {
  131. time_exec(sm->debug_vals.mod_cyc, 
  132.   sm->mode_tx->modulator_s16(sm, p, sm->dma.ofragsz/2));
  133. } else {
  134. time_exec(sm->debug_vals.mod_cyc, 
  135.   sm->mode_tx->modulator_u8(sm, p, sm->dma.ofragsz));
  136. }
  137. sm->dma.ptt_cnt++;
  138. }
  139. }
  140. static inline void dma_init_transmit(struct sm_state *sm)
  141. {
  142. sm->dma.ofragptr = 0;
  143. sm->dma.ptt_cnt = 0;
  144. }
  145. static inline void dma_start_transmit(struct sm_state *sm)
  146. {
  147. sm->dma.ofragptr = 0;
  148. if (sm->dma.o16bit) {
  149. time_exec(sm->debug_vals.mod_cyc, 
  150.   sm->mode_tx->modulator_s16(sm, sm->dma.obuf, sm->dma.ofragsz/2));
  151. } else {
  152. time_exec(sm->debug_vals.mod_cyc, 
  153.   sm->mode_tx->modulator_u8(sm, sm->dma.obuf, sm->dma.ofragsz));
  154. }
  155. sm->dma.ptt_cnt = 1;
  156. }
  157. static inline void dma_clear_transmit(struct sm_state *sm)
  158. {
  159. sm->dma.ptt_cnt = 0;
  160. memset(sm->dma.obuf, (sm->dma.o16bit) ? 0 : 0x80, sm->dma.ofragsz * NUM_FRAGMENTS);
  161. }
  162. /* --------------------------------------------------------------------- */
  163. static inline void dma_receive(struct sm_state *sm, unsigned int curfrag)
  164. {
  165. void *p;
  166. while (sm->dma.ifragptr != curfrag) {
  167. if (sm->dma.ifragptr)
  168. p = (unsigned char *)sm->dma.ibuf + 
  169. sm->dma.ifragsz * sm->dma.ifragptr;
  170. else {
  171. p = (unsigned char *)sm->dma.ibuf + NUM_FRAGMENTS * sm->dma.ifragsz;
  172. memcpy(p, sm->dma.ibuf, sm->dma.ifragsz);
  173. }
  174. if (sm->dma.o16bit) {
  175. time_exec(sm->debug_vals.demod_cyc, 
  176.   sm->mode_rx->demodulator_s16(sm, p, sm->dma.ifragsz/2));
  177. } else {
  178. time_exec(sm->debug_vals.demod_cyc, 
  179.   sm->mode_rx->demodulator_u8(sm, p, sm->dma.ifragsz));
  180. }
  181. sm->dma.ifragptr = (sm->dma.ifragptr + 1) % NUM_FRAGMENTS;
  182. }
  183. }
  184. static inline void dma_init_receive(struct sm_state *sm)
  185. {
  186. sm->dma.ifragptr = 0;
  187. }
  188. /* --------------------------------------------------------------------- */
  189. #endif /* _SMDMA_H */