File: /usr/src/linux/drivers/net/hamradio/soundmodem/sm.h

1     /*****************************************************************************/
2     
3     /*
4      *	sm.h  --  soundcard radio modem driver internal header.
5      *
6      *	Copyright (C) 1996-1999  Thomas Sailer (sailer@ife.ee.ethz.ch)
7      *
8      *	This program is free software; you can redistribute it and/or modify
9      *	it under the terms of the GNU General Public License as published by
10      *	the Free Software Foundation; either version 2 of the License, or
11      *	(at your option) any later version.
12      *
13      *	This program is distributed in the hope that it will be useful,
14      *	but WITHOUT ANY WARRANTY; without even the implied warranty of
15      *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16      *	GNU General Public License for more details.
17      *
18      *	You should have received a copy of the GNU General Public License
19      *	along with this program; if not, write to the Free Software
20      *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21      *
22      *  Please note that the GPL allows you to use the driver, NOT the radio.
23      *  In order to use the radio, you need a license from the communications
24      *  authority of your country.
25      *
26      */
27     
28     #ifndef _SM_H
29     #define _SM_H
30     
31     /* ---------------------------------------------------------------------- */
32     
33     #include <linux/hdlcdrv.h>
34     #include <linux/soundmodem.h>
35     #include <asm/processor.h>
36     #include <linux/bitops.h>
37     #include <linux/parport.h>
38     
39     #define SM_DEBUG
40     
41     /* ---------------------------------------------------------------------- */
42     /*
43      * Information that need to be kept for each board.
44      */
45     
46     struct sm_state {
47     	struct hdlcdrv_state hdrv;
48     
49     	const struct modem_tx_info *mode_tx;
50     	const struct modem_rx_info *mode_rx;
51     
52     	const struct hardware_info *hwdrv;
53     
54     	struct pardevice *pardev;
55     
56     	/*
57     	 * Hardware (soundcard) access routines state
58     	 */
59     	struct {
60     		void *ibuf;
61     		unsigned int ifragsz;
62     		unsigned int ifragptr;
63     		unsigned int i16bit;
64     		void *obuf;
65     		unsigned int ofragsz;
66     		unsigned int ofragptr;
67     		unsigned int o16bit;
68     		int ptt_cnt;
69     	} dma;
70     
71     	union {
72     		long hw[32/sizeof(long)];
73     	} hw;
74     
75     	/*
76     	 * state of the modem code
77     	 */
78     	union {
79     		long m[48/sizeof(long)];
80     	} m;
81     	union {
82     		long d[256/sizeof(long)];
83     	} d;
84     
85     #define DIAGDATALEN 64
86     	struct diag_data {
87     		unsigned int mode;
88     		unsigned int flags;
89     		volatile int ptr;
90     		short data[DIAGDATALEN];
91     	} diag;
92     
93     
94     #ifdef SM_DEBUG
95     	struct debug_vals {
96     		unsigned long last_jiffies;
97     		unsigned cur_intcnt;
98     		unsigned last_intcnt;
99     		unsigned mod_cyc;
100     		unsigned demod_cyc;
101     		unsigned dma_residue;
102     	} debug_vals;
103     #endif /* SM_DEBUG */
104     };
105     
106     /* ---------------------------------------------------------------------- */
107     /*
108      * Mode definition structure
109      */
110     
111     struct modem_tx_info {
112     	const char *name;
113     	unsigned int loc_storage;
114     	int srate;
115     	int bitrate;
116             void (*modulator_u8)(struct sm_state *, unsigned char *, unsigned int);
117             void (*modulator_s16)(struct sm_state *, short *, unsigned int);
118             void (*init)(struct sm_state *);
119     };
120     
121     struct modem_rx_info {
122     	const char *name;
123     	unsigned int loc_storage;
124     	int srate;
125     	int bitrate;
126     	unsigned int overlap;
127     	unsigned int sperbit;
128             void (*demodulator_u8)(struct sm_state *, const unsigned char *, unsigned int);
129             void (*demodulator_s16)(struct sm_state *, const short *, unsigned int);
130             void (*init)(struct sm_state *);
131     };
132     
133     /* ---------------------------------------------------------------------- */
134     /*
135      * Soundcard driver definition structure
136      */
137     
138     struct hardware_info {
139     	char *hw_name; /* used for request_{region,irq,dma} */
140     	unsigned int loc_storage;
141     	/*
142     	 * mode specific open/close
143     	 */
144     	int (*open)(struct net_device *, struct sm_state *);
145     	int (*close)(struct net_device *, struct sm_state *);
146     	int (*ioctl)(struct net_device *, struct sm_state *, struct ifreq *,
147     		     struct hdlcdrv_ioctl *, int);
148     	int (*sethw)(struct net_device *, struct sm_state *, char *);
149     };
150     
151     /* --------------------------------------------------------------------- */
152     
153     extern const char sm_drvname[];
154     extern const char sm_drvinfo[];
155     
156     /* --------------------------------------------------------------------- */
157     /*
158      * ===================== diagnostics stuff ===============================
159      */
160     
161     extern inline void diag_trigger(struct sm_state *sm)
162     {
163     	if (sm->diag.ptr < 0)
164     		if (!(sm->diag.flags & SM_DIAGFLAG_DCDGATE) || sm->hdrv.hdlcrx.dcd)
165     			sm->diag.ptr = 0;
166     }
167     
168     /* --------------------------------------------------------------------- */
169     
170     #define SHRT_MAX ((short)(((unsigned short)(~0U))>>1))
171     #define SHRT_MIN (-SHRT_MAX-1)
172     
173     extern inline void diag_add(struct sm_state *sm, int valinp, int valdemod)
174     {
175     	int val;
176     
177     	if ((sm->diag.mode != SM_DIAGMODE_INPUT &&
178     	     sm->diag.mode != SM_DIAGMODE_DEMOD) ||
179     	    sm->diag.ptr >= DIAGDATALEN || sm->diag.ptr < 0)
180     		return;
181     	val = (sm->diag.mode == SM_DIAGMODE_DEMOD) ? valdemod : valinp;
182     	/* clip */
183     	if (val > SHRT_MAX)
184     		val = SHRT_MAX;
185     	if (val < SHRT_MIN)
186     		val = SHRT_MIN;
187     	sm->diag.data[sm->diag.ptr++] = val;
188     }
189     
190     /* --------------------------------------------------------------------- */
191     
192     extern inline void diag_add_one(struct sm_state *sm, int val)
193     {
194     	if ((sm->diag.mode != SM_DIAGMODE_INPUT &&
195     	     sm->diag.mode != SM_DIAGMODE_DEMOD) ||
196     	    sm->diag.ptr >= DIAGDATALEN || sm->diag.ptr < 0)
197     		return;
198     	/* clip */
199     	if (val > SHRT_MAX)
200     		val = SHRT_MAX;
201     	if (val < SHRT_MIN)
202     		val = SHRT_MIN;
203     	sm->diag.data[sm->diag.ptr++] = val;
204     }
205     
206     /* --------------------------------------------------------------------- */
207     
208     static inline void diag_add_constellation(struct sm_state *sm, int vali, int valq)
209     {
210     	if ((sm->diag.mode != SM_DIAGMODE_CONSTELLATION) ||
211     	    sm->diag.ptr >= DIAGDATALEN-1 || sm->diag.ptr < 0)
212     		return;
213     	/* clip */
214     	if (vali > SHRT_MAX)
215     		vali = SHRT_MAX;
216     	if (vali < SHRT_MIN)
217     		vali = SHRT_MIN;
218     	if (valq > SHRT_MAX)
219     		valq = SHRT_MAX;
220     	if (valq < SHRT_MIN)
221     		valq = SHRT_MIN;
222     	sm->diag.data[sm->diag.ptr++] = vali;
223     	sm->diag.data[sm->diag.ptr++] = valq;
224     }
225     
226     /* --------------------------------------------------------------------- */
227     /*
228      * ===================== utility functions ===============================
229      */
230     
231     #if 0
232     extern inline unsigned int hweight32(unsigned int w)
233     	__attribute__ ((unused));
234     extern inline unsigned int hweight16(unsigned short w)
235     	__attribute__ ((unused));
236     extern inline unsigned int hweight8(unsigned char w)
237             __attribute__ ((unused));
238     
239     extern inline unsigned int hweight32(unsigned int w)
240     {
241             unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
242             res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
243             res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
244             res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
245             return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
246     }
247     
248     extern inline unsigned int hweight16(unsigned short w)
249     {
250             unsigned short res = (w & 0x5555) + ((w >> 1) & 0x5555);
251             res = (res & 0x3333) + ((res >> 2) & 0x3333);
252             res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F);
253             return (res & 0x00FF) + ((res >> 8) & 0x00FF);
254     }
255     
256     extern inline unsigned int hweight8(unsigned char w)
257     {
258             unsigned short res = (w & 0x55) + ((w >> 1) & 0x55);
259             res = (res & 0x33) + ((res >> 2) & 0x33);
260             return (res & 0x0F) + ((res >> 4) & 0x0F);
261     }
262     
263     #endif
264     
265     extern inline unsigned int gcd(unsigned int x, unsigned int y)
266     	__attribute__ ((unused));
267     extern inline unsigned int lcm(unsigned int x, unsigned int y)
268     	__attribute__ ((unused));
269     
270     extern inline unsigned int gcd(unsigned int x, unsigned int y)
271     {
272     	for (;;) {
273     		if (!x)
274     			return y;
275     		if (!y)
276     			return x;
277     		if (x > y)
278     			x %= y;
279     		else
280     			y %= x;
281     	}
282     }
283     
284     extern inline unsigned int lcm(unsigned int x, unsigned int y)
285     {
286     	return x * y / gcd(x, y);
287     }
288     
289     /* --------------------------------------------------------------------- */
290     /*
291      * ===================== profiling =======================================
292      */
293     
294     
295     #ifdef __i386__
296     
297     #include <asm/msr.h>
298     
299     /*
300      * only do 32bit cycle counter arithmetic; we hope we won't overflow.
301      * in fact, overflowing modems would require over 2THz CPU clock speeds :-)
302      */
303     
304     #define time_exec(var,cmd)                                              \
305     ({                                                                      \
306     	if (cpu_has_tsc) {                                              \
307     		unsigned int cnt1, cnt2;                                \
308     		rdtscl(cnt1);                                           \
309     		cmd;                                                    \
310     		rdtscl(cnt2);                                           \
311     		var = cnt2-cnt1;                                        \
312     	} else {                                                        \
313     		cmd;                                                    \
314     	}                                                               \
315     })
316     
317     #else /* __i386__ */
318     
319     #define time_exec(var,cmd) cmd
320     
321     #endif /* __i386__ */
322     
323     /* --------------------------------------------------------------------- */
324     
325     extern const struct modem_tx_info sm_afsk1200_tx;
326     extern const struct modem_tx_info sm_afsk2400_7_tx;
327     extern const struct modem_tx_info sm_afsk2400_8_tx;
328     extern const struct modem_tx_info sm_afsk2666_tx;
329     extern const struct modem_tx_info sm_psk4800_tx;
330     extern const struct modem_tx_info sm_hapn4800_8_tx;
331     extern const struct modem_tx_info sm_hapn4800_10_tx;
332     extern const struct modem_tx_info sm_hapn4800_pm8_tx;
333     extern const struct modem_tx_info sm_hapn4800_pm10_tx;
334     extern const struct modem_tx_info sm_fsk9600_4_tx;
335     extern const struct modem_tx_info sm_fsk9600_5_tx;
336     
337     extern const struct modem_rx_info sm_afsk1200_rx;
338     extern const struct modem_rx_info sm_afsk2400_7_rx;
339     extern const struct modem_rx_info sm_afsk2400_8_rx;
340     extern const struct modem_rx_info sm_afsk2666_rx;
341     extern const struct modem_rx_info sm_psk4800_rx;
342     extern const struct modem_rx_info sm_hapn4800_8_rx;
343     extern const struct modem_rx_info sm_hapn4800_10_rx;
344     extern const struct modem_rx_info sm_hapn4800_pm8_rx;
345     extern const struct modem_rx_info sm_hapn4800_pm10_rx;
346     extern const struct modem_rx_info sm_fsk9600_4_rx;
347     extern const struct modem_rx_info sm_fsk9600_5_rx;
348     
349     extern const struct hardware_info sm_hw_sbc;
350     extern const struct hardware_info sm_hw_sbcfdx;
351     extern const struct hardware_info sm_hw_wss;
352     extern const struct hardware_info sm_hw_wssfdx;
353     
354     extern const struct modem_tx_info *sm_modem_tx_table[];
355     extern const struct modem_rx_info *sm_modem_rx_table[];
356     extern const struct hardware_info *sm_hardware_table[];
357     
358     /* --------------------------------------------------------------------- */
359     
360     void sm_output_status(struct sm_state *sm);
361     /*void sm_output_open(struct sm_state *sm);*/
362     /*void sm_output_close(struct sm_state *sm);*/
363     
364     /* --------------------------------------------------------------------- */
365     
366     extern void inline sm_int_freq(struct sm_state *sm)
367     {
368     #ifdef SM_DEBUG
369     	unsigned long cur_jiffies = jiffies;
370     	/*
371     	 * measure the interrupt frequency
372     	 */
373     	sm->debug_vals.cur_intcnt++;
374     	if ((cur_jiffies - sm->debug_vals.last_jiffies) >= HZ) {
375     		sm->debug_vals.last_jiffies = cur_jiffies;
376     		sm->debug_vals.last_intcnt = sm->debug_vals.cur_intcnt;
377     		sm->debug_vals.cur_intcnt = 0;
378     	}
379     #endif /* SM_DEBUG */
380     }
381     
382     /* --------------------------------------------------------------------- */
383     #endif /* _SM_H */
384