xref: /openbmc/linux/include/linux/hdlcdrv.h (revision 25ec92fb)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * hdlcdrv.h  -- HDLC packet radio network driver.
41da177e4SLinus Torvalds  * The Linux soundcard driver for 1200 baud and 9600 baud packet radio
51da177e4SLinus Torvalds  * (C) 1996-1998 by Thomas Sailer, HB9JNX/AE4WA
61da177e4SLinus Torvalds  */
71da177e4SLinus Torvalds #ifndef _HDLCDRV_H
81da177e4SLinus Torvalds #define _HDLCDRV_H
91da177e4SLinus Torvalds 
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds #include <linux/netdevice.h>
121da177e4SLinus Torvalds #include <linux/if.h>
131da177e4SLinus Torvalds #include <linux/spinlock.h>
14607ca46eSDavid Howells #include <uapi/linux/hdlcdrv.h>
151da177e4SLinus Torvalds 
161da177e4SLinus Torvalds #define HDLCDRV_MAGIC      0x5ac6e778
171da177e4SLinus Torvalds #define HDLCDRV_HDLCBUFFER  32 /* should be a power of 2 for speed reasons */
181da177e4SLinus Torvalds #define HDLCDRV_BITBUFFER  256 /* should be a power of 2 for speed reasons */
191da177e4SLinus Torvalds #undef HDLCDRV_LOOPBACK  /* define for HDLC debugging purposes */
201da177e4SLinus Torvalds #define HDLCDRV_DEBUG
211da177e4SLinus Torvalds 
221da177e4SLinus Torvalds /* maximum packet length, excluding CRC */
231da177e4SLinus Torvalds #define HDLCDRV_MAXFLEN             400
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds 
261da177e4SLinus Torvalds struct hdlcdrv_hdlcbuffer {
271da177e4SLinus Torvalds 	spinlock_t lock;
281da177e4SLinus Torvalds 	unsigned rd, wr;
291da177e4SLinus Torvalds 	unsigned short buf[HDLCDRV_HDLCBUFFER];
301da177e4SLinus Torvalds };
311da177e4SLinus Torvalds 
321da177e4SLinus Torvalds #ifdef HDLCDRV_DEBUG
331da177e4SLinus Torvalds struct hdlcdrv_bitbuffer {
341da177e4SLinus Torvalds 	unsigned int rd;
351da177e4SLinus Torvalds 	unsigned int wr;
361da177e4SLinus Torvalds 	unsigned int shreg;
371da177e4SLinus Torvalds 	unsigned char buffer[HDLCDRV_BITBUFFER];
381da177e4SLinus Torvalds };
391da177e4SLinus Torvalds 
hdlcdrv_add_bitbuffer(struct hdlcdrv_bitbuffer * buf,unsigned int bit)401da177e4SLinus Torvalds static inline void hdlcdrv_add_bitbuffer(struct hdlcdrv_bitbuffer *buf,
411da177e4SLinus Torvalds 					 unsigned int bit)
421da177e4SLinus Torvalds {
431da177e4SLinus Torvalds 	unsigned char new;
441da177e4SLinus Torvalds 
451da177e4SLinus Torvalds 	new = buf->shreg & 1;
461da177e4SLinus Torvalds 	buf->shreg >>= 1;
471da177e4SLinus Torvalds 	buf->shreg |= (!!bit) << 7;
481da177e4SLinus Torvalds 	if (new) {
491da177e4SLinus Torvalds 		buf->buffer[buf->wr] = buf->shreg;
501da177e4SLinus Torvalds 		buf->wr = (buf->wr+1) % sizeof(buf->buffer);
511da177e4SLinus Torvalds 		buf->shreg = 0x80;
521da177e4SLinus Torvalds 	}
531da177e4SLinus Torvalds }
541da177e4SLinus Torvalds 
hdlcdrv_add_bitbuffer_word(struct hdlcdrv_bitbuffer * buf,unsigned int bits)551da177e4SLinus Torvalds static inline void hdlcdrv_add_bitbuffer_word(struct hdlcdrv_bitbuffer *buf,
561da177e4SLinus Torvalds 					      unsigned int bits)
571da177e4SLinus Torvalds {
581da177e4SLinus Torvalds 	buf->buffer[buf->wr] = bits & 0xff;
591da177e4SLinus Torvalds 	buf->wr = (buf->wr+1) % sizeof(buf->buffer);
601da177e4SLinus Torvalds 	buf->buffer[buf->wr] = (bits >> 8) & 0xff;
611da177e4SLinus Torvalds 	buf->wr = (buf->wr+1) % sizeof(buf->buffer);
621da177e4SLinus Torvalds 
631da177e4SLinus Torvalds }
641da177e4SLinus Torvalds #endif /* HDLCDRV_DEBUG */
651da177e4SLinus Torvalds 
661da177e4SLinus Torvalds /* -------------------------------------------------------------------- */
671da177e4SLinus Torvalds /*
681da177e4SLinus Torvalds  * Information that need to be kept for each driver.
691da177e4SLinus Torvalds  */
701da177e4SLinus Torvalds 
711da177e4SLinus Torvalds struct hdlcdrv_ops {
721da177e4SLinus Torvalds 	/*
731da177e4SLinus Torvalds 	 * first some informations needed by the hdlcdrv routines
741da177e4SLinus Torvalds 	 */
751da177e4SLinus Torvalds 	const char *drvname;
761da177e4SLinus Torvalds 	const char *drvinfo;
771da177e4SLinus Torvalds 	/*
781da177e4SLinus Torvalds 	 * the routines called by the hdlcdrv routines
791da177e4SLinus Torvalds 	 */
801da177e4SLinus Torvalds 	int (*open)(struct net_device *);
811da177e4SLinus Torvalds 	int (*close)(struct net_device *);
82*25ec92fbSArnd Bergmann 	int (*ioctl)(struct net_device *, void __user *,
831da177e4SLinus Torvalds 		     struct hdlcdrv_ioctl *, int);
841da177e4SLinus Torvalds };
851da177e4SLinus Torvalds 
861da177e4SLinus Torvalds struct hdlcdrv_state {
871da177e4SLinus Torvalds 	int magic;
881da177e4SLinus Torvalds 	int opened;
891da177e4SLinus Torvalds 
901da177e4SLinus Torvalds 	const struct hdlcdrv_ops *ops;
911da177e4SLinus Torvalds 
921da177e4SLinus Torvalds 	struct {
931da177e4SLinus Torvalds 		int bitrate;
941da177e4SLinus Torvalds 	} par;
951da177e4SLinus Torvalds 
961da177e4SLinus Torvalds 	struct hdlcdrv_pttoutput {
971da177e4SLinus Torvalds 		int dma2;
981da177e4SLinus Torvalds 		int seriobase;
991da177e4SLinus Torvalds 		int pariobase;
1001da177e4SLinus Torvalds 		int midiiobase;
1011da177e4SLinus Torvalds 		unsigned int flags;
1021da177e4SLinus Torvalds 	} ptt_out;
1031da177e4SLinus Torvalds 
1041da177e4SLinus Torvalds 	struct hdlcdrv_channel_params ch_params;
1051da177e4SLinus Torvalds 
1061da177e4SLinus Torvalds 	struct hdlcdrv_hdlcrx {
1071da177e4SLinus Torvalds 		struct hdlcdrv_hdlcbuffer hbuf;
10864b33619SAl Viro 		unsigned long in_hdlc_rx;
1091da177e4SLinus Torvalds 		/* 0 = sync hunt, != 0 receiving */
1101da177e4SLinus Torvalds 		int rx_state;
1111da177e4SLinus Torvalds 		unsigned int bitstream;
1121da177e4SLinus Torvalds 		unsigned int bitbuf;
1131da177e4SLinus Torvalds 		int numbits;
1141da177e4SLinus Torvalds 		unsigned char dcd;
1151da177e4SLinus Torvalds 
1161da177e4SLinus Torvalds 		int len;
1171da177e4SLinus Torvalds 		unsigned char *bp;
1181da177e4SLinus Torvalds 		unsigned char buffer[HDLCDRV_MAXFLEN+2];
1191da177e4SLinus Torvalds 	} hdlcrx;
1201da177e4SLinus Torvalds 
1211da177e4SLinus Torvalds 	struct hdlcdrv_hdlctx {
1221da177e4SLinus Torvalds 		struct hdlcdrv_hdlcbuffer hbuf;
123886a63e8SHannes Eder 		unsigned long in_hdlc_tx;
1241da177e4SLinus Torvalds 		/*
1251da177e4SLinus Torvalds 		 * 0 = send flags
1261da177e4SLinus Torvalds 		 * 1 = send txtail (flags)
1271da177e4SLinus Torvalds 		 * 2 = send packet
1281da177e4SLinus Torvalds 		 */
1291da177e4SLinus Torvalds 		int tx_state;
1301da177e4SLinus Torvalds 		int numflags;
1311da177e4SLinus Torvalds 		unsigned int bitstream;
1321da177e4SLinus Torvalds 		unsigned char ptt;
1331da177e4SLinus Torvalds 		int calibrate;
1341da177e4SLinus Torvalds 		int slotcnt;
1351da177e4SLinus Torvalds 
1361da177e4SLinus Torvalds 		unsigned int bitbuf;
1371da177e4SLinus Torvalds 		int numbits;
1381da177e4SLinus Torvalds 
1391da177e4SLinus Torvalds 		int len;
1401da177e4SLinus Torvalds 		unsigned char *bp;
1411da177e4SLinus Torvalds 		unsigned char buffer[HDLCDRV_MAXFLEN+2];
1421da177e4SLinus Torvalds 	} hdlctx;
1431da177e4SLinus Torvalds 
1441da177e4SLinus Torvalds #ifdef HDLCDRV_DEBUG
1451da177e4SLinus Torvalds 	struct hdlcdrv_bitbuffer bitbuf_channel;
1461da177e4SLinus Torvalds 	struct hdlcdrv_bitbuffer bitbuf_hdlc;
1471da177e4SLinus Torvalds #endif /* HDLCDRV_DEBUG */
1481da177e4SLinus Torvalds 
1491da177e4SLinus Torvalds 	int ptt_keyed;
1501da177e4SLinus Torvalds 
1511da177e4SLinus Torvalds 	/* queued skb for transmission */
1521da177e4SLinus Torvalds 	struct sk_buff *skb;
1531da177e4SLinus Torvalds };
1541da177e4SLinus Torvalds 
1551da177e4SLinus Torvalds 
1561da177e4SLinus Torvalds /* -------------------------------------------------------------------- */
1571da177e4SLinus Torvalds 
hdlcdrv_hbuf_full(struct hdlcdrv_hdlcbuffer * hb)1581da177e4SLinus Torvalds static inline int hdlcdrv_hbuf_full(struct hdlcdrv_hdlcbuffer *hb)
1591da177e4SLinus Torvalds {
1601da177e4SLinus Torvalds 	unsigned long flags;
1611da177e4SLinus Torvalds 	int ret;
1621da177e4SLinus Torvalds 
1631da177e4SLinus Torvalds 	spin_lock_irqsave(&hb->lock, flags);
1641da177e4SLinus Torvalds 	ret = !((HDLCDRV_HDLCBUFFER - 1 + hb->rd - hb->wr) % HDLCDRV_HDLCBUFFER);
1651da177e4SLinus Torvalds 	spin_unlock_irqrestore(&hb->lock, flags);
1661da177e4SLinus Torvalds 	return ret;
1671da177e4SLinus Torvalds }
1681da177e4SLinus Torvalds 
1691da177e4SLinus Torvalds /* -------------------------------------------------------------------- */
1701da177e4SLinus Torvalds 
hdlcdrv_hbuf_empty(struct hdlcdrv_hdlcbuffer * hb)1711da177e4SLinus Torvalds static inline int hdlcdrv_hbuf_empty(struct hdlcdrv_hdlcbuffer *hb)
1721da177e4SLinus Torvalds {
1731da177e4SLinus Torvalds 	unsigned long flags;
1741da177e4SLinus Torvalds 	int ret;
1751da177e4SLinus Torvalds 
1761da177e4SLinus Torvalds 	spin_lock_irqsave(&hb->lock, flags);
1771da177e4SLinus Torvalds 	ret = (hb->rd == hb->wr);
1781da177e4SLinus Torvalds 	spin_unlock_irqrestore(&hb->lock, flags);
1791da177e4SLinus Torvalds 	return ret;
1801da177e4SLinus Torvalds }
1811da177e4SLinus Torvalds 
1821da177e4SLinus Torvalds /* -------------------------------------------------------------------- */
1831da177e4SLinus Torvalds 
hdlcdrv_hbuf_get(struct hdlcdrv_hdlcbuffer * hb)1841da177e4SLinus Torvalds static inline unsigned short hdlcdrv_hbuf_get(struct hdlcdrv_hdlcbuffer *hb)
1851da177e4SLinus Torvalds {
1861da177e4SLinus Torvalds 	unsigned long flags;
1871da177e4SLinus Torvalds 	unsigned short val;
1881da177e4SLinus Torvalds 	unsigned newr;
1891da177e4SLinus Torvalds 
1901da177e4SLinus Torvalds 	spin_lock_irqsave(&hb->lock, flags);
1911da177e4SLinus Torvalds 	if (hb->rd == hb->wr)
1921da177e4SLinus Torvalds 		val = 0;
1931da177e4SLinus Torvalds 	else {
1941da177e4SLinus Torvalds 		newr = (hb->rd+1) % HDLCDRV_HDLCBUFFER;
1951da177e4SLinus Torvalds 		val = hb->buf[hb->rd];
1961da177e4SLinus Torvalds 		hb->rd = newr;
1971da177e4SLinus Torvalds 	}
1981da177e4SLinus Torvalds 	spin_unlock_irqrestore(&hb->lock, flags);
1991da177e4SLinus Torvalds 	return val;
2001da177e4SLinus Torvalds }
2011da177e4SLinus Torvalds 
2021da177e4SLinus Torvalds /* -------------------------------------------------------------------- */
2031da177e4SLinus Torvalds 
hdlcdrv_hbuf_put(struct hdlcdrv_hdlcbuffer * hb,unsigned short val)2041da177e4SLinus Torvalds static inline void hdlcdrv_hbuf_put(struct hdlcdrv_hdlcbuffer *hb,
2051da177e4SLinus Torvalds 				    unsigned short val)
2061da177e4SLinus Torvalds {
2071da177e4SLinus Torvalds 	unsigned newp;
2081da177e4SLinus Torvalds 	unsigned long flags;
2091da177e4SLinus Torvalds 
2101da177e4SLinus Torvalds 	spin_lock_irqsave(&hb->lock, flags);
2111da177e4SLinus Torvalds 	newp = (hb->wr+1) % HDLCDRV_HDLCBUFFER;
2121da177e4SLinus Torvalds 	if (newp != hb->rd) {
2131da177e4SLinus Torvalds 		hb->buf[hb->wr] = val & 0xffff;
2141da177e4SLinus Torvalds 		hb->wr = newp;
2151da177e4SLinus Torvalds 	}
2161da177e4SLinus Torvalds 	spin_unlock_irqrestore(&hb->lock, flags);
2171da177e4SLinus Torvalds }
2181da177e4SLinus Torvalds 
2191da177e4SLinus Torvalds /* -------------------------------------------------------------------- */
2201da177e4SLinus Torvalds 
hdlcdrv_putbits(struct hdlcdrv_state * s,unsigned int bits)2211da177e4SLinus Torvalds static inline void hdlcdrv_putbits(struct hdlcdrv_state *s, unsigned int bits)
2221da177e4SLinus Torvalds {
2231da177e4SLinus Torvalds 	hdlcdrv_hbuf_put(&s->hdlcrx.hbuf, bits);
2241da177e4SLinus Torvalds }
2251da177e4SLinus Torvalds 
hdlcdrv_getbits(struct hdlcdrv_state * s)2261da177e4SLinus Torvalds static inline unsigned int hdlcdrv_getbits(struct hdlcdrv_state *s)
2271da177e4SLinus Torvalds {
2281da177e4SLinus Torvalds 	unsigned int ret;
2291da177e4SLinus Torvalds 
2301da177e4SLinus Torvalds 	if (hdlcdrv_hbuf_empty(&s->hdlctx.hbuf)) {
2311da177e4SLinus Torvalds 		if (s->hdlctx.calibrate > 0)
2321da177e4SLinus Torvalds 			s->hdlctx.calibrate--;
2331da177e4SLinus Torvalds 		else
2341da177e4SLinus Torvalds 			s->hdlctx.ptt = 0;
2351da177e4SLinus Torvalds 		ret = 0;
2361da177e4SLinus Torvalds 	} else
2371da177e4SLinus Torvalds 		ret = hdlcdrv_hbuf_get(&s->hdlctx.hbuf);
2381da177e4SLinus Torvalds #ifdef HDLCDRV_LOOPBACK
2391da177e4SLinus Torvalds 	hdlcdrv_hbuf_put(&s->hdlcrx.hbuf, ret);
2401da177e4SLinus Torvalds #endif /* HDLCDRV_LOOPBACK */
2411da177e4SLinus Torvalds 	return ret;
2421da177e4SLinus Torvalds }
2431da177e4SLinus Torvalds 
hdlcdrv_channelbit(struct hdlcdrv_state * s,unsigned int bit)2441da177e4SLinus Torvalds static inline void hdlcdrv_channelbit(struct hdlcdrv_state *s, unsigned int bit)
2451da177e4SLinus Torvalds {
2461da177e4SLinus Torvalds #ifdef HDLCDRV_DEBUG
2471da177e4SLinus Torvalds 	hdlcdrv_add_bitbuffer(&s->bitbuf_channel, bit);
2481da177e4SLinus Torvalds #endif /* HDLCDRV_DEBUG */
2491da177e4SLinus Torvalds }
2501da177e4SLinus Torvalds 
hdlcdrv_setdcd(struct hdlcdrv_state * s,int dcd)2511da177e4SLinus Torvalds static inline void hdlcdrv_setdcd(struct hdlcdrv_state *s, int dcd)
2521da177e4SLinus Torvalds {
2531da177e4SLinus Torvalds 	s->hdlcrx.dcd = !!dcd;
2541da177e4SLinus Torvalds }
2551da177e4SLinus Torvalds 
hdlcdrv_ptt(struct hdlcdrv_state * s)2561da177e4SLinus Torvalds static inline int hdlcdrv_ptt(struct hdlcdrv_state *s)
2571da177e4SLinus Torvalds {
2581da177e4SLinus Torvalds 	return s->hdlctx.ptt || (s->hdlctx.calibrate > 0);
2591da177e4SLinus Torvalds }
2601da177e4SLinus Torvalds 
2611da177e4SLinus Torvalds /* -------------------------------------------------------------------- */
2621da177e4SLinus Torvalds 
2631da177e4SLinus Torvalds void hdlcdrv_receiver(struct net_device *, struct hdlcdrv_state *);
2641da177e4SLinus Torvalds void hdlcdrv_transmitter(struct net_device *, struct hdlcdrv_state *);
2651da177e4SLinus Torvalds void hdlcdrv_arbitrate(struct net_device *, struct hdlcdrv_state *);
2661da177e4SLinus Torvalds struct net_device *hdlcdrv_register(const struct hdlcdrv_ops *ops,
2671da177e4SLinus Torvalds 				    unsigned int privsize, const char *ifname,
2681da177e4SLinus Torvalds 				    unsigned int baseaddr, unsigned int irq,
2691da177e4SLinus Torvalds 				    unsigned int dma);
2701da177e4SLinus Torvalds void hdlcdrv_unregister(struct net_device *dev);
2711da177e4SLinus Torvalds 
2721da177e4SLinus Torvalds /* -------------------------------------------------------------------- */
2731da177e4SLinus Torvalds 
2741da177e4SLinus Torvalds 
2751da177e4SLinus Torvalds 
2761da177e4SLinus Torvalds #endif /* _HDLCDRV_H */
277