diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-12-16 06:32:09 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1997-12-16 06:32:09 +0000 |
commit | 1d68c48efe2d331857dfd4dfa4104fb366c100c5 (patch) | |
tree | e6c894ae6b00193b25948fa58cf596ee633053d7 /drivers/net/hamradio/soundmodem/smdma.h | |
parent | aa944aa3453e47706685bc562711a9e87375941e (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.h | 217 |
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 */ + + + |