summaryrefslogtreecommitdiffstats
path: root/drivers/net/hamradio/soundmodem/smdma.h
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-12-16 06:32:09 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-12-16 06:32:09 +0000
commit1d68c48efe2d331857dfd4dfa4104fb366c100c5 (patch)
treee6c894ae6b00193b25948fa58cf596ee633053d7 /drivers/net/hamradio/soundmodem/smdma.h
parentaa944aa3453e47706685bc562711a9e87375941e (diff)
Merge with Linux 2.1.72, part 3.
Diffstat (limited to 'drivers/net/hamradio/soundmodem/smdma.h')
-rw-r--r--drivers/net/hamradio/soundmodem/smdma.h217
1 files changed, 217 insertions, 0 deletions
diff --git a/drivers/net/hamradio/soundmodem/smdma.h b/drivers/net/hamradio/soundmodem/smdma.h
new file mode 100644
index 000000000..44e457a7a
--- /dev/null
+++ b/drivers/net/hamradio/soundmodem/smdma.h
@@ -0,0 +1,217 @@
+/*****************************************************************************/
+
+/*
+ * smdma.h -- soundcard radio modem driver dma buffer routines.
+ *
+ * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please note that the GPL allows you to use the driver, NOT the radio.
+ * In order to use the radio, you need a license from the communications
+ * authority of your country.
+ *
+ */
+
+#ifndef _SMDMA_H
+#define _SMDMA_H
+
+/* ---------------------------------------------------------------------- */
+
+#include "sm.h"
+
+/* ---------------------------------------------------------------------- */
+
+#define DMA_MODE_AUTOINIT 0x10
+#define NUM_FRAGMENTS 4
+
+/*
+ * NOTE: make sure that hdlcdrv_hdlcbuffer contains enough space
+ * for the modulator to fill the whole DMA buffer without underrun
+ * at the highest possible baud rate, otherwise the TX state machine will
+ * not work correctly. That is (9k6 FSK): HDLCDRV_HDLCBUFFER > 6*NUM_FRAGMENTS
+ */
+
+/* --------------------------------------------------------------------- */
+/*
+ * ===================== DMA buffer management ===========================
+ */
+
+/*
+ * returns the number of samples per fragment
+ */
+extern __inline__ unsigned int dma_setup(struct sm_state *sm, int send, unsigned int dmanr)
+{
+ if (send) {
+ disable_dma(dmanr);
+ clear_dma_ff(dmanr);
+ set_dma_mode(dmanr, DMA_MODE_WRITE | DMA_MODE_AUTOINIT);
+ set_dma_addr(dmanr, virt_to_bus(sm->dma.obuf));
+ set_dma_count(dmanr, sm->dma.ofragsz * NUM_FRAGMENTS);
+ enable_dma(dmanr);
+ if (sm->dma.o16bit)
+ return sm->dma.ofragsz/2;
+ return sm->dma.ofragsz;
+ } else {
+ disable_dma(dmanr);
+ clear_dma_ff(dmanr);
+ set_dma_mode(dmanr, DMA_MODE_READ | DMA_MODE_AUTOINIT);
+ set_dma_addr(dmanr, virt_to_bus(sm->dma.ibuf));
+ set_dma_count(dmanr, sm->dma.ifragsz * NUM_FRAGMENTS);
+ enable_dma(dmanr);
+ if (sm->dma.i16bit)
+ return sm->dma.ifragsz/2;
+ return sm->dma.ifragsz;
+ }
+}
+
+/* --------------------------------------------------------------------- */
+
+extern __inline__ unsigned int dma_ptr(struct sm_state *sm, int send, unsigned int dmanr,
+ unsigned int *curfrag)
+{
+ unsigned int dmaptr, sz, frg, offs;
+
+ dmaptr = get_dma_residue(dmanr);
+ if (send) {
+ sz = sm->dma.ofragsz * NUM_FRAGMENTS;
+ if (dmaptr == 0 || dmaptr > sz)
+ dmaptr = sz;
+ dmaptr--;
+ frg = dmaptr / sm->dma.ofragsz;
+ offs = (dmaptr % sm->dma.ofragsz) + 1;
+ *curfrag = NUM_FRAGMENTS - 1 - frg;
+#ifdef SM_DEBUG
+ if (!sm->debug_vals.dma_residue || offs < sm->debug_vals.dma_residue)
+ sm->debug_vals.dma_residue = offs;
+#endif /* SM_DEBUG */
+ if (sm->dma.o16bit)
+ return offs/2;
+ return offs;
+ } else {
+ sz = sm->dma.ifragsz * NUM_FRAGMENTS;
+ if (dmaptr == 0 || dmaptr > sz)
+ dmaptr = sz;
+ dmaptr--;
+ frg = dmaptr / sm->dma.ifragsz;
+ offs = (dmaptr % sm->dma.ifragsz) + 1;
+ *curfrag = NUM_FRAGMENTS - 1 - frg;
+#ifdef SM_DEBUG
+ if (!sm->debug_vals.dma_residue || offs < sm->debug_vals.dma_residue)
+ sm->debug_vals.dma_residue = offs;
+#endif /* SM_DEBUG */
+ if (sm->dma.i16bit)
+ return offs/2;
+ return offs;
+ }
+}
+
+/* --------------------------------------------------------------------- */
+
+extern __inline__ int dma_end_transmit(struct sm_state *sm, unsigned int curfrag)
+{
+ unsigned int diff = (NUM_FRAGMENTS + curfrag - sm->dma.ofragptr) % NUM_FRAGMENTS;
+
+ sm->dma.ofragptr = curfrag;
+ if (sm->dma.ptt_cnt <= 0) {
+ sm->dma.ptt_cnt = 0;
+ return 0;
+ }
+ sm->dma.ptt_cnt -= diff;
+ if (sm->dma.ptt_cnt <= 0) {
+ sm->dma.ptt_cnt = 0;
+ return -1;
+ }
+ return 0;
+}
+
+extern __inline__ void dma_transmit(struct sm_state *sm)
+{
+ void *p;
+
+ while (sm->dma.ptt_cnt < NUM_FRAGMENTS && hdlcdrv_ptt(&sm->hdrv)) {
+ p = (unsigned char *)sm->dma.obuf + sm->dma.ofragsz *
+ ((sm->dma.ofragptr + sm->dma.ptt_cnt) % NUM_FRAGMENTS);
+ if (sm->dma.o16bit) {
+ time_exec(sm->debug_vals.mod_cyc,
+ sm->mode_tx->modulator_s16(sm, p, sm->dma.ofragsz/2));
+ } else {
+ time_exec(sm->debug_vals.mod_cyc,
+ sm->mode_tx->modulator_u8(sm, p, sm->dma.ofragsz));
+ }
+ sm->dma.ptt_cnt++;
+ }
+}
+
+extern __inline__ void dma_init_transmit(struct sm_state *sm)
+{
+ sm->dma.ofragptr = 0;
+ sm->dma.ptt_cnt = 0;
+}
+
+extern __inline__ void dma_start_transmit(struct sm_state *sm)
+{
+ sm->dma.ofragptr = 0;
+ if (sm->dma.o16bit) {
+ time_exec(sm->debug_vals.mod_cyc,
+ sm->mode_tx->modulator_s16(sm, sm->dma.obuf, sm->dma.ofragsz/2));
+ } else {
+ time_exec(sm->debug_vals.mod_cyc,
+ sm->mode_tx->modulator_u8(sm, sm->dma.obuf, sm->dma.ofragsz));
+ }
+ sm->dma.ptt_cnt = 1;
+}
+
+extern __inline__ void dma_clear_transmit(struct sm_state *sm)
+{
+ sm->dma.ptt_cnt = 0;
+ memset(sm->dma.obuf, (sm->dma.o16bit) ? 0 : 0x80, sm->dma.ofragsz * NUM_FRAGMENTS);
+}
+
+/* --------------------------------------------------------------------- */
+
+extern __inline__ void dma_receive(struct sm_state *sm, unsigned int curfrag)
+{
+ void *p;
+
+ while (sm->dma.ifragptr != curfrag) {
+ if (sm->dma.ifragptr)
+ p = (unsigned char *)sm->dma.ibuf +
+ sm->dma.ifragsz * sm->dma.ifragptr;
+ else {
+ p = (unsigned char *)sm->dma.ibuf + NUM_FRAGMENTS * sm->dma.ifragsz;
+ memcpy(p, sm->dma.ibuf, sm->dma.ifragsz);
+ }
+ if (sm->dma.o16bit) {
+ time_exec(sm->debug_vals.demod_cyc,
+ sm->mode_rx->demodulator_s16(sm, p, sm->dma.ifragsz/2));
+ } else {
+ time_exec(sm->debug_vals.demod_cyc,
+ sm->mode_rx->demodulator_u8(sm, p, sm->dma.ifragsz));
+ }
+ sm->dma.ifragptr = (sm->dma.ifragptr + 1) % NUM_FRAGMENTS;
+ }
+}
+
+extern __inline__ void dma_init_receive(struct sm_state *sm)
+{
+ sm->dma.ifragptr = 0;
+}
+
+/* --------------------------------------------------------------------- */
+#endif /* _SMDMA_H */
+
+
+