1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*****************************************************************************/
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun /*
5*4882a593Smuzhiyun * yam.c -- YAM radio modem driver.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright (C) 1998 Frederic Rible F1OAT (frible@teaser.fr)
8*4882a593Smuzhiyun * Adapted from baycom.c driver written by Thomas Sailer (sailer@ife.ee.ethz.ch)
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * Please note that the GPL allows you to use the driver, NOT the radio.
11*4882a593Smuzhiyun * In order to use the radio, you need a license from the communications
12*4882a593Smuzhiyun * authority of your country.
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun * History:
15*4882a593Smuzhiyun * 0.0 F1OAT 06.06.98 Begin of work with baycom.c source code V 0.3
16*4882a593Smuzhiyun * 0.1 F1OAT 07.06.98 Add timer polling routine for channel arbitration
17*4882a593Smuzhiyun * 0.2 F6FBB 08.06.98 Added delay after FPGA programming
18*4882a593Smuzhiyun * 0.3 F6FBB 29.07.98 Delayed PTT implementation for dupmode=2
19*4882a593Smuzhiyun * 0.4 F6FBB 30.07.98 Added TxTail, Slottime and Persistence
20*4882a593Smuzhiyun * 0.5 F6FBB 01.08.98 Shared IRQs, /proc/net and network statistics
21*4882a593Smuzhiyun * 0.6 F6FBB 25.08.98 Added 1200Bds format
22*4882a593Smuzhiyun * 0.7 F6FBB 12.09.98 Added to the kernel configuration
23*4882a593Smuzhiyun * 0.8 F6FBB 14.10.98 Fixed slottime/persistence timing bug
24*4882a593Smuzhiyun * OK1ZIA 2.09.01 Fixed "kfree_skb on hard IRQ"
25*4882a593Smuzhiyun * using dev_kfree_skb_any(). (important in 2.4 kernel)
26*4882a593Smuzhiyun */
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun /*****************************************************************************/
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #include <linux/module.h>
31*4882a593Smuzhiyun #include <linux/types.h>
32*4882a593Smuzhiyun #include <linux/net.h>
33*4882a593Smuzhiyun #include <linux/in.h>
34*4882a593Smuzhiyun #include <linux/if.h>
35*4882a593Smuzhiyun #include <linux/slab.h>
36*4882a593Smuzhiyun #include <linux/errno.h>
37*4882a593Smuzhiyun #include <linux/bitops.h>
38*4882a593Smuzhiyun #include <linux/random.h>
39*4882a593Smuzhiyun #include <asm/io.h>
40*4882a593Smuzhiyun #include <linux/interrupt.h>
41*4882a593Smuzhiyun #include <linux/ioport.h>
42*4882a593Smuzhiyun #include <linux/firmware.h>
43*4882a593Smuzhiyun #include <linux/platform_device.h>
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun #include <linux/netdevice.h>
46*4882a593Smuzhiyun #include <linux/if_arp.h>
47*4882a593Smuzhiyun #include <linux/etherdevice.h>
48*4882a593Smuzhiyun #include <linux/skbuff.h>
49*4882a593Smuzhiyun #include <net/ax25.h>
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun #include <linux/kernel.h>
52*4882a593Smuzhiyun #include <linux/proc_fs.h>
53*4882a593Smuzhiyun #include <linux/seq_file.h>
54*4882a593Smuzhiyun #include <net/net_namespace.h>
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun #include <linux/uaccess.h>
57*4882a593Smuzhiyun #include <linux/init.h>
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun #include <linux/yam.h>
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun /* --------------------------------------------------------------------- */
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun static const char yam_drvname[] = "yam";
64*4882a593Smuzhiyun static const char yam_drvinfo[] __initconst = KERN_INFO \
65*4882a593Smuzhiyun "YAM driver version 0.8 by F1OAT/F6FBB\n";
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun /* --------------------------------------------------------------------- */
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun #define FIRMWARE_9600 "yam/9600.bin"
70*4882a593Smuzhiyun #define FIRMWARE_1200 "yam/1200.bin"
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun #define YAM_9600 1
73*4882a593Smuzhiyun #define YAM_1200 2
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun #define NR_PORTS 4
76*4882a593Smuzhiyun #define YAM_MAGIC 0xF10A7654
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun /* Transmitter states */
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun #define TX_OFF 0
81*4882a593Smuzhiyun #define TX_HEAD 1
82*4882a593Smuzhiyun #define TX_DATA 2
83*4882a593Smuzhiyun #define TX_CRC1 3
84*4882a593Smuzhiyun #define TX_CRC2 4
85*4882a593Smuzhiyun #define TX_TAIL 5
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun #define YAM_MAX_FRAME 1024
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun #define DEFAULT_BITRATE 9600 /* bps */
90*4882a593Smuzhiyun #define DEFAULT_HOLDD 10 /* sec */
91*4882a593Smuzhiyun #define DEFAULT_TXD 300 /* ms */
92*4882a593Smuzhiyun #define DEFAULT_TXTAIL 10 /* ms */
93*4882a593Smuzhiyun #define DEFAULT_SLOT 100 /* ms */
94*4882a593Smuzhiyun #define DEFAULT_PERS 64 /* 0->255 */
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun struct yam_port {
97*4882a593Smuzhiyun int magic;
98*4882a593Smuzhiyun int bitrate;
99*4882a593Smuzhiyun int baudrate;
100*4882a593Smuzhiyun int iobase;
101*4882a593Smuzhiyun int irq;
102*4882a593Smuzhiyun int dupmode;
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun struct net_device *dev;
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun int nb_rxint;
107*4882a593Smuzhiyun int nb_mdint;
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun /* Parameters section */
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun int txd; /* tx delay */
112*4882a593Smuzhiyun int holdd; /* duplex ptt delay */
113*4882a593Smuzhiyun int txtail; /* txtail delay */
114*4882a593Smuzhiyun int slot; /* slottime */
115*4882a593Smuzhiyun int pers; /* persistence */
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun /* Tx section */
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun int tx_state;
120*4882a593Smuzhiyun int tx_count;
121*4882a593Smuzhiyun int slotcnt;
122*4882a593Smuzhiyun unsigned char tx_buf[YAM_MAX_FRAME];
123*4882a593Smuzhiyun int tx_len;
124*4882a593Smuzhiyun int tx_crcl, tx_crch;
125*4882a593Smuzhiyun struct sk_buff_head send_queue; /* Packets awaiting transmission */
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun /* Rx section */
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun int dcd;
130*4882a593Smuzhiyun unsigned char rx_buf[YAM_MAX_FRAME];
131*4882a593Smuzhiyun int rx_len;
132*4882a593Smuzhiyun int rx_crcl, rx_crch;
133*4882a593Smuzhiyun };
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun struct yam_mcs {
136*4882a593Smuzhiyun unsigned char bits[YAM_FPGA_SIZE];
137*4882a593Smuzhiyun int bitrate;
138*4882a593Smuzhiyun struct yam_mcs *next;
139*4882a593Smuzhiyun };
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun static struct net_device *yam_devs[NR_PORTS];
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun static struct yam_mcs *yam_data;
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun static DEFINE_TIMER(yam_timer, NULL);
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun /* --------------------------------------------------------------------- */
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun #define RBR(iobase) (iobase+0)
150*4882a593Smuzhiyun #define THR(iobase) (iobase+0)
151*4882a593Smuzhiyun #define IER(iobase) (iobase+1)
152*4882a593Smuzhiyun #define IIR(iobase) (iobase+2)
153*4882a593Smuzhiyun #define FCR(iobase) (iobase+2)
154*4882a593Smuzhiyun #define LCR(iobase) (iobase+3)
155*4882a593Smuzhiyun #define MCR(iobase) (iobase+4)
156*4882a593Smuzhiyun #define LSR(iobase) (iobase+5)
157*4882a593Smuzhiyun #define MSR(iobase) (iobase+6)
158*4882a593Smuzhiyun #define SCR(iobase) (iobase+7)
159*4882a593Smuzhiyun #define DLL(iobase) (iobase+0)
160*4882a593Smuzhiyun #define DLM(iobase) (iobase+1)
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun #define YAM_EXTENT 8
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun /* Interrupt Identification Register Bit Masks */
165*4882a593Smuzhiyun #define IIR_NOPEND 1
166*4882a593Smuzhiyun #define IIR_MSR 0
167*4882a593Smuzhiyun #define IIR_TX 2
168*4882a593Smuzhiyun #define IIR_RX 4
169*4882a593Smuzhiyun #define IIR_LSR 6
170*4882a593Smuzhiyun #define IIR_TIMEOUT 12 /* Fifo mode only */
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun #define IIR_MASK 0x0F
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun /* Interrupt Enable Register Bit Masks */
175*4882a593Smuzhiyun #define IER_RX 1 /* enable rx interrupt */
176*4882a593Smuzhiyun #define IER_TX 2 /* enable tx interrupt */
177*4882a593Smuzhiyun #define IER_LSR 4 /* enable line status interrupts */
178*4882a593Smuzhiyun #define IER_MSR 8 /* enable modem status interrupts */
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun /* Modem Control Register Bit Masks */
181*4882a593Smuzhiyun #define MCR_DTR 0x01 /* DTR output */
182*4882a593Smuzhiyun #define MCR_RTS 0x02 /* RTS output */
183*4882a593Smuzhiyun #define MCR_OUT1 0x04 /* OUT1 output (not accessible in RS232) */
184*4882a593Smuzhiyun #define MCR_OUT2 0x08 /* Master Interrupt enable (must be set on PCs) */
185*4882a593Smuzhiyun #define MCR_LOOP 0x10 /* Loopback enable */
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun /* Modem Status Register Bit Masks */
188*4882a593Smuzhiyun #define MSR_DCTS 0x01 /* Delta CTS input */
189*4882a593Smuzhiyun #define MSR_DDSR 0x02 /* Delta DSR */
190*4882a593Smuzhiyun #define MSR_DRIN 0x04 /* Delta RI */
191*4882a593Smuzhiyun #define MSR_DDCD 0x08 /* Delta DCD */
192*4882a593Smuzhiyun #define MSR_CTS 0x10 /* CTS input */
193*4882a593Smuzhiyun #define MSR_DSR 0x20 /* DSR input */
194*4882a593Smuzhiyun #define MSR_RING 0x40 /* RI input */
195*4882a593Smuzhiyun #define MSR_DCD 0x80 /* DCD input */
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun /* line status register bit mask */
198*4882a593Smuzhiyun #define LSR_RXC 0x01
199*4882a593Smuzhiyun #define LSR_OE 0x02
200*4882a593Smuzhiyun #define LSR_PE 0x04
201*4882a593Smuzhiyun #define LSR_FE 0x08
202*4882a593Smuzhiyun #define LSR_BREAK 0x10
203*4882a593Smuzhiyun #define LSR_THRE 0x20
204*4882a593Smuzhiyun #define LSR_TSRE 0x40
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun /* Line Control Register Bit Masks */
207*4882a593Smuzhiyun #define LCR_DLAB 0x80
208*4882a593Smuzhiyun #define LCR_BREAK 0x40
209*4882a593Smuzhiyun #define LCR_PZERO 0x28
210*4882a593Smuzhiyun #define LCR_PEVEN 0x18
211*4882a593Smuzhiyun #define LCR_PODD 0x08
212*4882a593Smuzhiyun #define LCR_STOP1 0x00
213*4882a593Smuzhiyun #define LCR_STOP2 0x04
214*4882a593Smuzhiyun #define LCR_BIT5 0x00
215*4882a593Smuzhiyun #define LCR_BIT6 0x02
216*4882a593Smuzhiyun #define LCR_BIT7 0x01
217*4882a593Smuzhiyun #define LCR_BIT8 0x03
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun /* YAM Modem <-> UART Port mapping */
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun #define TX_RDY MSR_DCTS /* transmitter ready to send */
222*4882a593Smuzhiyun #define RX_DCD MSR_DCD /* carrier detect */
223*4882a593Smuzhiyun #define RX_FLAG MSR_RING /* hdlc flag received */
224*4882a593Smuzhiyun #define FPGA_DONE MSR_DSR /* FPGA is configured */
225*4882a593Smuzhiyun #define PTT_ON (MCR_RTS|MCR_OUT2) /* activate PTT */
226*4882a593Smuzhiyun #define PTT_OFF (MCR_DTR|MCR_OUT2) /* release PTT */
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun #define ENABLE_RXINT IER_RX /* enable uart rx interrupt during rx */
229*4882a593Smuzhiyun #define ENABLE_TXINT IER_MSR /* enable uart ms interrupt during tx */
230*4882a593Smuzhiyun #define ENABLE_RTXINT (IER_RX|IER_MSR) /* full duplex operations */
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun /*************************************************************************
234*4882a593Smuzhiyun * CRC Tables
235*4882a593Smuzhiyun ************************************************************************/
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun static const unsigned char chktabl[256] =
238*4882a593Smuzhiyun {0x00, 0x89, 0x12, 0x9b, 0x24, 0xad, 0x36, 0xbf, 0x48, 0xc1, 0x5a, 0xd3, 0x6c, 0xe5, 0x7e,
239*4882a593Smuzhiyun 0xf7, 0x81, 0x08, 0x93, 0x1a, 0xa5, 0x2c, 0xb7, 0x3e, 0xc9, 0x40, 0xdb, 0x52, 0xed, 0x64,
240*4882a593Smuzhiyun 0xff, 0x76, 0x02, 0x8b, 0x10, 0x99, 0x26, 0xaf, 0x34, 0xbd, 0x4a, 0xc3, 0x58, 0xd1, 0x6e,
241*4882a593Smuzhiyun 0xe7, 0x7c, 0xf5, 0x83, 0x0a, 0x91, 0x18, 0xa7, 0x2e, 0xb5, 0x3c, 0xcb, 0x42, 0xd9, 0x50,
242*4882a593Smuzhiyun 0xef, 0x66, 0xfd, 0x74, 0x04, 0x8d, 0x16, 0x9f, 0x20, 0xa9, 0x32, 0xbb, 0x4c, 0xc5, 0x5e,
243*4882a593Smuzhiyun 0xd7, 0x68, 0xe1, 0x7a, 0xf3, 0x85, 0x0c, 0x97, 0x1e, 0xa1, 0x28, 0xb3, 0x3a, 0xcd, 0x44,
244*4882a593Smuzhiyun 0xdf, 0x56, 0xe9, 0x60, 0xfb, 0x72, 0x06, 0x8f, 0x14, 0x9d, 0x22, 0xab, 0x30, 0xb9, 0x4e,
245*4882a593Smuzhiyun 0xc7, 0x5c, 0xd5, 0x6a, 0xe3, 0x78, 0xf1, 0x87, 0x0e, 0x95, 0x1c, 0xa3, 0x2a, 0xb1, 0x38,
246*4882a593Smuzhiyun 0xcf, 0x46, 0xdd, 0x54, 0xeb, 0x62, 0xf9, 0x70, 0x08, 0x81, 0x1a, 0x93, 0x2c, 0xa5, 0x3e,
247*4882a593Smuzhiyun 0xb7, 0x40, 0xc9, 0x52, 0xdb, 0x64, 0xed, 0x76, 0xff, 0x89, 0x00, 0x9b, 0x12, 0xad, 0x24,
248*4882a593Smuzhiyun 0xbf, 0x36, 0xc1, 0x48, 0xd3, 0x5a, 0xe5, 0x6c, 0xf7, 0x7e, 0x0a, 0x83, 0x18, 0x91, 0x2e,
249*4882a593Smuzhiyun 0xa7, 0x3c, 0xb5, 0x42, 0xcb, 0x50, 0xd9, 0x66, 0xef, 0x74, 0xfd, 0x8b, 0x02, 0x99, 0x10,
250*4882a593Smuzhiyun 0xaf, 0x26, 0xbd, 0x34, 0xc3, 0x4a, 0xd1, 0x58, 0xe7, 0x6e, 0xf5, 0x7c, 0x0c, 0x85, 0x1e,
251*4882a593Smuzhiyun 0x97, 0x28, 0xa1, 0x3a, 0xb3, 0x44, 0xcd, 0x56, 0xdf, 0x60, 0xe9, 0x72, 0xfb, 0x8d, 0x04,
252*4882a593Smuzhiyun 0x9f, 0x16, 0xa9, 0x20, 0xbb, 0x32, 0xc5, 0x4c, 0xd7, 0x5e, 0xe1, 0x68, 0xf3, 0x7a, 0x0e,
253*4882a593Smuzhiyun 0x87, 0x1c, 0x95, 0x2a, 0xa3, 0x38, 0xb1, 0x46, 0xcf, 0x54, 0xdd, 0x62, 0xeb, 0x70, 0xf9,
254*4882a593Smuzhiyun 0x8f, 0x06, 0x9d, 0x14, 0xab, 0x22, 0xb9, 0x30, 0xc7, 0x4e, 0xd5, 0x5c, 0xe3, 0x6a, 0xf1,
255*4882a593Smuzhiyun 0x78};
256*4882a593Smuzhiyun static const unsigned char chktabh[256] =
257*4882a593Smuzhiyun {0x00, 0x11, 0x23, 0x32, 0x46, 0x57, 0x65, 0x74, 0x8c, 0x9d, 0xaf, 0xbe, 0xca, 0xdb, 0xe9,
258*4882a593Smuzhiyun 0xf8, 0x10, 0x01, 0x33, 0x22, 0x56, 0x47, 0x75, 0x64, 0x9c, 0x8d, 0xbf, 0xae, 0xda, 0xcb,
259*4882a593Smuzhiyun 0xf9, 0xe8, 0x21, 0x30, 0x02, 0x13, 0x67, 0x76, 0x44, 0x55, 0xad, 0xbc, 0x8e, 0x9f, 0xeb,
260*4882a593Smuzhiyun 0xfa, 0xc8, 0xd9, 0x31, 0x20, 0x12, 0x03, 0x77, 0x66, 0x54, 0x45, 0xbd, 0xac, 0x9e, 0x8f,
261*4882a593Smuzhiyun 0xfb, 0xea, 0xd8, 0xc9, 0x42, 0x53, 0x61, 0x70, 0x04, 0x15, 0x27, 0x36, 0xce, 0xdf, 0xed,
262*4882a593Smuzhiyun 0xfc, 0x88, 0x99, 0xab, 0xba, 0x52, 0x43, 0x71, 0x60, 0x14, 0x05, 0x37, 0x26, 0xde, 0xcf,
263*4882a593Smuzhiyun 0xfd, 0xec, 0x98, 0x89, 0xbb, 0xaa, 0x63, 0x72, 0x40, 0x51, 0x25, 0x34, 0x06, 0x17, 0xef,
264*4882a593Smuzhiyun 0xfe, 0xcc, 0xdd, 0xa9, 0xb8, 0x8a, 0x9b, 0x73, 0x62, 0x50, 0x41, 0x35, 0x24, 0x16, 0x07,
265*4882a593Smuzhiyun 0xff, 0xee, 0xdc, 0xcd, 0xb9, 0xa8, 0x9a, 0x8b, 0x84, 0x95, 0xa7, 0xb6, 0xc2, 0xd3, 0xe1,
266*4882a593Smuzhiyun 0xf0, 0x08, 0x19, 0x2b, 0x3a, 0x4e, 0x5f, 0x6d, 0x7c, 0x94, 0x85, 0xb7, 0xa6, 0xd2, 0xc3,
267*4882a593Smuzhiyun 0xf1, 0xe0, 0x18, 0x09, 0x3b, 0x2a, 0x5e, 0x4f, 0x7d, 0x6c, 0xa5, 0xb4, 0x86, 0x97, 0xe3,
268*4882a593Smuzhiyun 0xf2, 0xc0, 0xd1, 0x29, 0x38, 0x0a, 0x1b, 0x6f, 0x7e, 0x4c, 0x5d, 0xb5, 0xa4, 0x96, 0x87,
269*4882a593Smuzhiyun 0xf3, 0xe2, 0xd0, 0xc1, 0x39, 0x28, 0x1a, 0x0b, 0x7f, 0x6e, 0x5c, 0x4d, 0xc6, 0xd7, 0xe5,
270*4882a593Smuzhiyun 0xf4, 0x80, 0x91, 0xa3, 0xb2, 0x4a, 0x5b, 0x69, 0x78, 0x0c, 0x1d, 0x2f, 0x3e, 0xd6, 0xc7,
271*4882a593Smuzhiyun 0xf5, 0xe4, 0x90, 0x81, 0xb3, 0xa2, 0x5a, 0x4b, 0x79, 0x68, 0x1c, 0x0d, 0x3f, 0x2e, 0xe7,
272*4882a593Smuzhiyun 0xf6, 0xc4, 0xd5, 0xa1, 0xb0, 0x82, 0x93, 0x6b, 0x7a, 0x48, 0x59, 0x2d, 0x3c, 0x0e, 0x1f,
273*4882a593Smuzhiyun 0xf7, 0xe6, 0xd4, 0xc5, 0xb1, 0xa0, 0x92, 0x83, 0x7b, 0x6a, 0x58, 0x49, 0x3d, 0x2c, 0x1e,
274*4882a593Smuzhiyun 0x0f};
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun /*************************************************************************
277*4882a593Smuzhiyun * FPGA functions
278*4882a593Smuzhiyun ************************************************************************/
279*4882a593Smuzhiyun
delay(int ms)280*4882a593Smuzhiyun static void delay(int ms)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun unsigned long timeout = jiffies + ((ms * HZ) / 1000);
283*4882a593Smuzhiyun while (time_before(jiffies, timeout))
284*4882a593Smuzhiyun cpu_relax();
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun /*
288*4882a593Smuzhiyun * reset FPGA
289*4882a593Smuzhiyun */
290*4882a593Smuzhiyun
fpga_reset(int iobase)291*4882a593Smuzhiyun static void fpga_reset(int iobase)
292*4882a593Smuzhiyun {
293*4882a593Smuzhiyun outb(0, IER(iobase));
294*4882a593Smuzhiyun outb(LCR_DLAB | LCR_BIT5, LCR(iobase));
295*4882a593Smuzhiyun outb(1, DLL(iobase));
296*4882a593Smuzhiyun outb(0, DLM(iobase));
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun outb(LCR_BIT5, LCR(iobase));
299*4882a593Smuzhiyun inb(LSR(iobase));
300*4882a593Smuzhiyun inb(MSR(iobase));
301*4882a593Smuzhiyun /* turn off FPGA supply voltage */
302*4882a593Smuzhiyun outb(MCR_OUT1 | MCR_OUT2, MCR(iobase));
303*4882a593Smuzhiyun delay(100);
304*4882a593Smuzhiyun /* turn on FPGA supply voltage again */
305*4882a593Smuzhiyun outb(MCR_DTR | MCR_RTS | MCR_OUT1 | MCR_OUT2, MCR(iobase));
306*4882a593Smuzhiyun delay(100);
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun /*
310*4882a593Smuzhiyun * send one byte to FPGA
311*4882a593Smuzhiyun */
312*4882a593Smuzhiyun
fpga_write(int iobase,unsigned char wrd)313*4882a593Smuzhiyun static int fpga_write(int iobase, unsigned char wrd)
314*4882a593Smuzhiyun {
315*4882a593Smuzhiyun unsigned char bit;
316*4882a593Smuzhiyun int k;
317*4882a593Smuzhiyun unsigned long timeout = jiffies + HZ / 10;
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun for (k = 0; k < 8; k++) {
320*4882a593Smuzhiyun bit = (wrd & 0x80) ? (MCR_RTS | MCR_DTR) : MCR_DTR;
321*4882a593Smuzhiyun outb(bit | MCR_OUT1 | MCR_OUT2, MCR(iobase));
322*4882a593Smuzhiyun wrd <<= 1;
323*4882a593Smuzhiyun outb(0xfc, THR(iobase));
324*4882a593Smuzhiyun while ((inb(LSR(iobase)) & LSR_TSRE) == 0)
325*4882a593Smuzhiyun if (time_after(jiffies, timeout))
326*4882a593Smuzhiyun return -1;
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun return 0;
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun /*
333*4882a593Smuzhiyun * predef should be 0 for loading user defined mcs
334*4882a593Smuzhiyun * predef should be YAM_1200 for loading predef 1200 mcs
335*4882a593Smuzhiyun * predef should be YAM_9600 for loading predef 9600 mcs
336*4882a593Smuzhiyun */
add_mcs(unsigned char * bits,int bitrate,unsigned int predef)337*4882a593Smuzhiyun static unsigned char *add_mcs(unsigned char *bits, int bitrate,
338*4882a593Smuzhiyun unsigned int predef)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun const char *fw_name[2] = {FIRMWARE_9600, FIRMWARE_1200};
341*4882a593Smuzhiyun const struct firmware *fw;
342*4882a593Smuzhiyun struct platform_device *pdev;
343*4882a593Smuzhiyun struct yam_mcs *p;
344*4882a593Smuzhiyun int err;
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun switch (predef) {
347*4882a593Smuzhiyun case 0:
348*4882a593Smuzhiyun fw = NULL;
349*4882a593Smuzhiyun break;
350*4882a593Smuzhiyun case YAM_1200:
351*4882a593Smuzhiyun case YAM_9600:
352*4882a593Smuzhiyun predef--;
353*4882a593Smuzhiyun pdev = platform_device_register_simple("yam", 0, NULL, 0);
354*4882a593Smuzhiyun if (IS_ERR(pdev)) {
355*4882a593Smuzhiyun printk(KERN_ERR "yam: Failed to register firmware\n");
356*4882a593Smuzhiyun return NULL;
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun err = request_firmware(&fw, fw_name[predef], &pdev->dev);
359*4882a593Smuzhiyun platform_device_unregister(pdev);
360*4882a593Smuzhiyun if (err) {
361*4882a593Smuzhiyun printk(KERN_ERR "Failed to load firmware \"%s\"\n",
362*4882a593Smuzhiyun fw_name[predef]);
363*4882a593Smuzhiyun return NULL;
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun if (fw->size != YAM_FPGA_SIZE) {
366*4882a593Smuzhiyun printk(KERN_ERR "Bogus length %zu in firmware \"%s\"\n",
367*4882a593Smuzhiyun fw->size, fw_name[predef]);
368*4882a593Smuzhiyun release_firmware(fw);
369*4882a593Smuzhiyun return NULL;
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun bits = (unsigned char *)fw->data;
372*4882a593Smuzhiyun break;
373*4882a593Smuzhiyun default:
374*4882a593Smuzhiyun printk(KERN_ERR "yam: Invalid predef number %u\n", predef);
375*4882a593Smuzhiyun return NULL;
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun /* If it already exists, replace the bit data */
379*4882a593Smuzhiyun p = yam_data;
380*4882a593Smuzhiyun while (p) {
381*4882a593Smuzhiyun if (p->bitrate == bitrate) {
382*4882a593Smuzhiyun memcpy(p->bits, bits, YAM_FPGA_SIZE);
383*4882a593Smuzhiyun goto out;
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun p = p->next;
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun /* Allocate a new mcs */
389*4882a593Smuzhiyun if ((p = kmalloc(sizeof(struct yam_mcs), GFP_KERNEL)) == NULL) {
390*4882a593Smuzhiyun release_firmware(fw);
391*4882a593Smuzhiyun return NULL;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun memcpy(p->bits, bits, YAM_FPGA_SIZE);
394*4882a593Smuzhiyun p->bitrate = bitrate;
395*4882a593Smuzhiyun p->next = yam_data;
396*4882a593Smuzhiyun yam_data = p;
397*4882a593Smuzhiyun out:
398*4882a593Smuzhiyun release_firmware(fw);
399*4882a593Smuzhiyun return p->bits;
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun
get_mcs(int bitrate)402*4882a593Smuzhiyun static unsigned char *get_mcs(int bitrate)
403*4882a593Smuzhiyun {
404*4882a593Smuzhiyun struct yam_mcs *p;
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun p = yam_data;
407*4882a593Smuzhiyun while (p) {
408*4882a593Smuzhiyun if (p->bitrate == bitrate)
409*4882a593Smuzhiyun return p->bits;
410*4882a593Smuzhiyun p = p->next;
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun /* Load predefined mcs data */
414*4882a593Smuzhiyun switch (bitrate) {
415*4882a593Smuzhiyun case 1200:
416*4882a593Smuzhiyun /* setting predef as YAM_1200 for loading predef 1200 mcs */
417*4882a593Smuzhiyun return add_mcs(NULL, bitrate, YAM_1200);
418*4882a593Smuzhiyun default:
419*4882a593Smuzhiyun /* setting predef as YAM_9600 for loading predef 9600 mcs */
420*4882a593Smuzhiyun return add_mcs(NULL, bitrate, YAM_9600);
421*4882a593Smuzhiyun }
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun /*
425*4882a593Smuzhiyun * download bitstream to FPGA
426*4882a593Smuzhiyun * data is contained in bits[] array in yam1200.h resp. yam9600.h
427*4882a593Smuzhiyun */
428*4882a593Smuzhiyun
fpga_download(int iobase,int bitrate)429*4882a593Smuzhiyun static int fpga_download(int iobase, int bitrate)
430*4882a593Smuzhiyun {
431*4882a593Smuzhiyun int i, rc;
432*4882a593Smuzhiyun unsigned char *pbits;
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun pbits = get_mcs(bitrate);
435*4882a593Smuzhiyun if (pbits == NULL)
436*4882a593Smuzhiyun return -1;
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun fpga_reset(iobase);
439*4882a593Smuzhiyun for (i = 0; i < YAM_FPGA_SIZE; i++) {
440*4882a593Smuzhiyun if (fpga_write(iobase, pbits[i])) {
441*4882a593Smuzhiyun printk(KERN_ERR "yam: error in write cycle\n");
442*4882a593Smuzhiyun return -1; /* write... */
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun fpga_write(iobase, 0xFF);
447*4882a593Smuzhiyun rc = inb(MSR(iobase)); /* check DONE signal */
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun /* Needed for some hardwares */
450*4882a593Smuzhiyun delay(50);
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun return (rc & MSR_DSR) ? 0 : -1;
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun /************************************************************************
457*4882a593Smuzhiyun * Serial port init
458*4882a593Smuzhiyun ************************************************************************/
459*4882a593Smuzhiyun
yam_set_uart(struct net_device * dev)460*4882a593Smuzhiyun static void yam_set_uart(struct net_device *dev)
461*4882a593Smuzhiyun {
462*4882a593Smuzhiyun struct yam_port *yp = netdev_priv(dev);
463*4882a593Smuzhiyun int divisor = 115200 / yp->baudrate;
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun outb(0, IER(dev->base_addr));
466*4882a593Smuzhiyun outb(LCR_DLAB | LCR_BIT8, LCR(dev->base_addr));
467*4882a593Smuzhiyun outb(divisor, DLL(dev->base_addr));
468*4882a593Smuzhiyun outb(0, DLM(dev->base_addr));
469*4882a593Smuzhiyun outb(LCR_BIT8, LCR(dev->base_addr));
470*4882a593Smuzhiyun outb(PTT_OFF, MCR(dev->base_addr));
471*4882a593Smuzhiyun outb(0x00, FCR(dev->base_addr));
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun /* Flush pending irq */
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun inb(RBR(dev->base_addr));
476*4882a593Smuzhiyun inb(MSR(dev->base_addr));
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun /* Enable rx irq */
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun outb(ENABLE_RTXINT, IER(dev->base_addr));
481*4882a593Smuzhiyun }
482*4882a593Smuzhiyun
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun /* --------------------------------------------------------------------- */
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun enum uart {
487*4882a593Smuzhiyun c_uart_unknown, c_uart_8250,
488*4882a593Smuzhiyun c_uart_16450, c_uart_16550, c_uart_16550A
489*4882a593Smuzhiyun };
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun static const char *uart_str[] =
492*4882a593Smuzhiyun {"unknown", "8250", "16450", "16550", "16550A"};
493*4882a593Smuzhiyun
yam_check_uart(unsigned int iobase)494*4882a593Smuzhiyun static enum uart yam_check_uart(unsigned int iobase)
495*4882a593Smuzhiyun {
496*4882a593Smuzhiyun unsigned char b1, b2, b3;
497*4882a593Smuzhiyun enum uart u;
498*4882a593Smuzhiyun enum uart uart_tab[] =
499*4882a593Smuzhiyun {c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A};
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun b1 = inb(MCR(iobase));
502*4882a593Smuzhiyun outb(b1 | 0x10, MCR(iobase)); /* loopback mode */
503*4882a593Smuzhiyun b2 = inb(MSR(iobase));
504*4882a593Smuzhiyun outb(0x1a, MCR(iobase));
505*4882a593Smuzhiyun b3 = inb(MSR(iobase)) & 0xf0;
506*4882a593Smuzhiyun outb(b1, MCR(iobase)); /* restore old values */
507*4882a593Smuzhiyun outb(b2, MSR(iobase));
508*4882a593Smuzhiyun if (b3 != 0x90)
509*4882a593Smuzhiyun return c_uart_unknown;
510*4882a593Smuzhiyun inb(RBR(iobase));
511*4882a593Smuzhiyun inb(RBR(iobase));
512*4882a593Smuzhiyun outb(0x01, FCR(iobase)); /* enable FIFOs */
513*4882a593Smuzhiyun u = uart_tab[(inb(IIR(iobase)) >> 6) & 3];
514*4882a593Smuzhiyun if (u == c_uart_16450) {
515*4882a593Smuzhiyun outb(0x5a, SCR(iobase));
516*4882a593Smuzhiyun b1 = inb(SCR(iobase));
517*4882a593Smuzhiyun outb(0xa5, SCR(iobase));
518*4882a593Smuzhiyun b2 = inb(SCR(iobase));
519*4882a593Smuzhiyun if ((b1 != 0x5a) || (b2 != 0xa5))
520*4882a593Smuzhiyun u = c_uart_8250;
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun return u;
523*4882a593Smuzhiyun }
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun /******************************************************************************
526*4882a593Smuzhiyun * Rx Section
527*4882a593Smuzhiyun ******************************************************************************/
yam_rx_flag(struct net_device * dev,struct yam_port * yp)528*4882a593Smuzhiyun static inline void yam_rx_flag(struct net_device *dev, struct yam_port *yp)
529*4882a593Smuzhiyun {
530*4882a593Smuzhiyun if (yp->dcd && yp->rx_len >= 3 && yp->rx_len < YAM_MAX_FRAME) {
531*4882a593Smuzhiyun int pkt_len = yp->rx_len - 2 + 1; /* -CRC + kiss */
532*4882a593Smuzhiyun struct sk_buff *skb;
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun if ((yp->rx_crch & yp->rx_crcl) != 0xFF) {
535*4882a593Smuzhiyun /* Bad crc */
536*4882a593Smuzhiyun } else {
537*4882a593Smuzhiyun if (!(skb = dev_alloc_skb(pkt_len))) {
538*4882a593Smuzhiyun printk(KERN_WARNING "%s: memory squeeze, dropping packet\n", dev->name);
539*4882a593Smuzhiyun ++dev->stats.rx_dropped;
540*4882a593Smuzhiyun } else {
541*4882a593Smuzhiyun unsigned char *cp;
542*4882a593Smuzhiyun cp = skb_put(skb, pkt_len);
543*4882a593Smuzhiyun *cp++ = 0; /* KISS kludge */
544*4882a593Smuzhiyun memcpy(cp, yp->rx_buf, pkt_len - 1);
545*4882a593Smuzhiyun skb->protocol = ax25_type_trans(skb, dev);
546*4882a593Smuzhiyun netif_rx(skb);
547*4882a593Smuzhiyun ++dev->stats.rx_packets;
548*4882a593Smuzhiyun }
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun yp->rx_len = 0;
552*4882a593Smuzhiyun yp->rx_crcl = 0x21;
553*4882a593Smuzhiyun yp->rx_crch = 0xf3;
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun
yam_rx_byte(struct net_device * dev,struct yam_port * yp,unsigned char rxb)556*4882a593Smuzhiyun static inline void yam_rx_byte(struct net_device *dev, struct yam_port *yp, unsigned char rxb)
557*4882a593Smuzhiyun {
558*4882a593Smuzhiyun if (yp->rx_len < YAM_MAX_FRAME) {
559*4882a593Smuzhiyun unsigned char c = yp->rx_crcl;
560*4882a593Smuzhiyun yp->rx_crcl = (chktabl[c] ^ yp->rx_crch);
561*4882a593Smuzhiyun yp->rx_crch = (chktabh[c] ^ rxb);
562*4882a593Smuzhiyun yp->rx_buf[yp->rx_len++] = rxb;
563*4882a593Smuzhiyun }
564*4882a593Smuzhiyun }
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun /********************************************************************************
567*4882a593Smuzhiyun * TX Section
568*4882a593Smuzhiyun ********************************************************************************/
569*4882a593Smuzhiyun
ptt_on(struct net_device * dev)570*4882a593Smuzhiyun static void ptt_on(struct net_device *dev)
571*4882a593Smuzhiyun {
572*4882a593Smuzhiyun outb(PTT_ON, MCR(dev->base_addr));
573*4882a593Smuzhiyun }
574*4882a593Smuzhiyun
ptt_off(struct net_device * dev)575*4882a593Smuzhiyun static void ptt_off(struct net_device *dev)
576*4882a593Smuzhiyun {
577*4882a593Smuzhiyun outb(PTT_OFF, MCR(dev->base_addr));
578*4882a593Smuzhiyun }
579*4882a593Smuzhiyun
yam_send_packet(struct sk_buff * skb,struct net_device * dev)580*4882a593Smuzhiyun static netdev_tx_t yam_send_packet(struct sk_buff *skb,
581*4882a593Smuzhiyun struct net_device *dev)
582*4882a593Smuzhiyun {
583*4882a593Smuzhiyun struct yam_port *yp = netdev_priv(dev);
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun if (skb->protocol == htons(ETH_P_IP))
586*4882a593Smuzhiyun return ax25_ip_xmit(skb);
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun skb_queue_tail(&yp->send_queue, skb);
589*4882a593Smuzhiyun netif_trans_update(dev);
590*4882a593Smuzhiyun return NETDEV_TX_OK;
591*4882a593Smuzhiyun }
592*4882a593Smuzhiyun
yam_start_tx(struct net_device * dev,struct yam_port * yp)593*4882a593Smuzhiyun static void yam_start_tx(struct net_device *dev, struct yam_port *yp)
594*4882a593Smuzhiyun {
595*4882a593Smuzhiyun if ((yp->tx_state == TX_TAIL) || (yp->txd == 0))
596*4882a593Smuzhiyun yp->tx_count = 1;
597*4882a593Smuzhiyun else
598*4882a593Smuzhiyun yp->tx_count = (yp->bitrate * yp->txd) / 8000;
599*4882a593Smuzhiyun yp->tx_state = TX_HEAD;
600*4882a593Smuzhiyun ptt_on(dev);
601*4882a593Smuzhiyun }
602*4882a593Smuzhiyun
yam_arbitrate(struct net_device * dev)603*4882a593Smuzhiyun static void yam_arbitrate(struct net_device *dev)
604*4882a593Smuzhiyun {
605*4882a593Smuzhiyun struct yam_port *yp = netdev_priv(dev);
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun if (yp->magic != YAM_MAGIC || yp->tx_state != TX_OFF ||
608*4882a593Smuzhiyun skb_queue_empty(&yp->send_queue))
609*4882a593Smuzhiyun return;
610*4882a593Smuzhiyun /* tx_state is TX_OFF and there is data to send */
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun if (yp->dupmode) {
613*4882a593Smuzhiyun /* Full duplex mode, don't wait */
614*4882a593Smuzhiyun yam_start_tx(dev, yp);
615*4882a593Smuzhiyun return;
616*4882a593Smuzhiyun }
617*4882a593Smuzhiyun if (yp->dcd) {
618*4882a593Smuzhiyun /* DCD on, wait slotime ... */
619*4882a593Smuzhiyun yp->slotcnt = yp->slot / 10;
620*4882a593Smuzhiyun return;
621*4882a593Smuzhiyun }
622*4882a593Smuzhiyun /* Is slottime passed ? */
623*4882a593Smuzhiyun if ((--yp->slotcnt) > 0)
624*4882a593Smuzhiyun return;
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun yp->slotcnt = yp->slot / 10;
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun /* is random > persist ? */
629*4882a593Smuzhiyun if ((prandom_u32() % 256) > yp->pers)
630*4882a593Smuzhiyun return;
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun yam_start_tx(dev, yp);
633*4882a593Smuzhiyun }
634*4882a593Smuzhiyun
yam_dotimer(struct timer_list * unused)635*4882a593Smuzhiyun static void yam_dotimer(struct timer_list *unused)
636*4882a593Smuzhiyun {
637*4882a593Smuzhiyun int i;
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun for (i = 0; i < NR_PORTS; i++) {
640*4882a593Smuzhiyun struct net_device *dev = yam_devs[i];
641*4882a593Smuzhiyun if (dev && netif_running(dev))
642*4882a593Smuzhiyun yam_arbitrate(dev);
643*4882a593Smuzhiyun }
644*4882a593Smuzhiyun yam_timer.expires = jiffies + HZ / 100;
645*4882a593Smuzhiyun add_timer(&yam_timer);
646*4882a593Smuzhiyun }
647*4882a593Smuzhiyun
yam_tx_byte(struct net_device * dev,struct yam_port * yp)648*4882a593Smuzhiyun static void yam_tx_byte(struct net_device *dev, struct yam_port *yp)
649*4882a593Smuzhiyun {
650*4882a593Smuzhiyun struct sk_buff *skb;
651*4882a593Smuzhiyun unsigned char b, temp;
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun switch (yp->tx_state) {
654*4882a593Smuzhiyun case TX_OFF:
655*4882a593Smuzhiyun break;
656*4882a593Smuzhiyun case TX_HEAD:
657*4882a593Smuzhiyun if (--yp->tx_count <= 0) {
658*4882a593Smuzhiyun if (!(skb = skb_dequeue(&yp->send_queue))) {
659*4882a593Smuzhiyun ptt_off(dev);
660*4882a593Smuzhiyun yp->tx_state = TX_OFF;
661*4882a593Smuzhiyun break;
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun yp->tx_state = TX_DATA;
664*4882a593Smuzhiyun if (skb->data[0] != 0) {
665*4882a593Smuzhiyun /* do_kiss_params(s, skb->data, skb->len); */
666*4882a593Smuzhiyun dev_kfree_skb_any(skb);
667*4882a593Smuzhiyun break;
668*4882a593Smuzhiyun }
669*4882a593Smuzhiyun yp->tx_len = skb->len - 1; /* strip KISS byte */
670*4882a593Smuzhiyun if (yp->tx_len >= YAM_MAX_FRAME || yp->tx_len < 2) {
671*4882a593Smuzhiyun dev_kfree_skb_any(skb);
672*4882a593Smuzhiyun break;
673*4882a593Smuzhiyun }
674*4882a593Smuzhiyun skb_copy_from_linear_data_offset(skb, 1,
675*4882a593Smuzhiyun yp->tx_buf,
676*4882a593Smuzhiyun yp->tx_len);
677*4882a593Smuzhiyun dev_kfree_skb_any(skb);
678*4882a593Smuzhiyun yp->tx_count = 0;
679*4882a593Smuzhiyun yp->tx_crcl = 0x21;
680*4882a593Smuzhiyun yp->tx_crch = 0xf3;
681*4882a593Smuzhiyun yp->tx_state = TX_DATA;
682*4882a593Smuzhiyun }
683*4882a593Smuzhiyun break;
684*4882a593Smuzhiyun case TX_DATA:
685*4882a593Smuzhiyun b = yp->tx_buf[yp->tx_count++];
686*4882a593Smuzhiyun outb(b, THR(dev->base_addr));
687*4882a593Smuzhiyun temp = yp->tx_crcl;
688*4882a593Smuzhiyun yp->tx_crcl = chktabl[temp] ^ yp->tx_crch;
689*4882a593Smuzhiyun yp->tx_crch = chktabh[temp] ^ b;
690*4882a593Smuzhiyun if (yp->tx_count >= yp->tx_len) {
691*4882a593Smuzhiyun yp->tx_state = TX_CRC1;
692*4882a593Smuzhiyun }
693*4882a593Smuzhiyun break;
694*4882a593Smuzhiyun case TX_CRC1:
695*4882a593Smuzhiyun yp->tx_crch = chktabl[yp->tx_crcl] ^ yp->tx_crch;
696*4882a593Smuzhiyun yp->tx_crcl = chktabh[yp->tx_crcl] ^ chktabl[yp->tx_crch] ^ 0xff;
697*4882a593Smuzhiyun outb(yp->tx_crcl, THR(dev->base_addr));
698*4882a593Smuzhiyun yp->tx_state = TX_CRC2;
699*4882a593Smuzhiyun break;
700*4882a593Smuzhiyun case TX_CRC2:
701*4882a593Smuzhiyun outb(chktabh[yp->tx_crch] ^ 0xFF, THR(dev->base_addr));
702*4882a593Smuzhiyun if (skb_queue_empty(&yp->send_queue)) {
703*4882a593Smuzhiyun yp->tx_count = (yp->bitrate * yp->txtail) / 8000;
704*4882a593Smuzhiyun if (yp->dupmode == 2)
705*4882a593Smuzhiyun yp->tx_count += (yp->bitrate * yp->holdd) / 8;
706*4882a593Smuzhiyun if (yp->tx_count == 0)
707*4882a593Smuzhiyun yp->tx_count = 1;
708*4882a593Smuzhiyun yp->tx_state = TX_TAIL;
709*4882a593Smuzhiyun } else {
710*4882a593Smuzhiyun yp->tx_count = 1;
711*4882a593Smuzhiyun yp->tx_state = TX_HEAD;
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun ++dev->stats.tx_packets;
714*4882a593Smuzhiyun break;
715*4882a593Smuzhiyun case TX_TAIL:
716*4882a593Smuzhiyun if (--yp->tx_count <= 0) {
717*4882a593Smuzhiyun yp->tx_state = TX_OFF;
718*4882a593Smuzhiyun ptt_off(dev);
719*4882a593Smuzhiyun }
720*4882a593Smuzhiyun break;
721*4882a593Smuzhiyun }
722*4882a593Smuzhiyun }
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun /***********************************************************************************
725*4882a593Smuzhiyun * ISR routine
726*4882a593Smuzhiyun ************************************************************************************/
727*4882a593Smuzhiyun
yam_interrupt(int irq,void * dev_id)728*4882a593Smuzhiyun static irqreturn_t yam_interrupt(int irq, void *dev_id)
729*4882a593Smuzhiyun {
730*4882a593Smuzhiyun struct net_device *dev;
731*4882a593Smuzhiyun struct yam_port *yp;
732*4882a593Smuzhiyun unsigned char iir;
733*4882a593Smuzhiyun int counter = 100;
734*4882a593Smuzhiyun int i;
735*4882a593Smuzhiyun int handled = 0;
736*4882a593Smuzhiyun
737*4882a593Smuzhiyun for (i = 0; i < NR_PORTS; i++) {
738*4882a593Smuzhiyun dev = yam_devs[i];
739*4882a593Smuzhiyun yp = netdev_priv(dev);
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun if (!netif_running(dev))
742*4882a593Smuzhiyun continue;
743*4882a593Smuzhiyun
744*4882a593Smuzhiyun while ((iir = IIR_MASK & inb(IIR(dev->base_addr))) != IIR_NOPEND) {
745*4882a593Smuzhiyun unsigned char msr = inb(MSR(dev->base_addr));
746*4882a593Smuzhiyun unsigned char lsr = inb(LSR(dev->base_addr));
747*4882a593Smuzhiyun unsigned char rxb;
748*4882a593Smuzhiyun
749*4882a593Smuzhiyun handled = 1;
750*4882a593Smuzhiyun
751*4882a593Smuzhiyun if (lsr & LSR_OE)
752*4882a593Smuzhiyun ++dev->stats.rx_fifo_errors;
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun yp->dcd = (msr & RX_DCD) ? 1 : 0;
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun if (--counter <= 0) {
757*4882a593Smuzhiyun printk(KERN_ERR "%s: too many irq iir=%d\n",
758*4882a593Smuzhiyun dev->name, iir);
759*4882a593Smuzhiyun goto out;
760*4882a593Smuzhiyun }
761*4882a593Smuzhiyun if (msr & TX_RDY) {
762*4882a593Smuzhiyun ++yp->nb_mdint;
763*4882a593Smuzhiyun yam_tx_byte(dev, yp);
764*4882a593Smuzhiyun }
765*4882a593Smuzhiyun if (lsr & LSR_RXC) {
766*4882a593Smuzhiyun ++yp->nb_rxint;
767*4882a593Smuzhiyun rxb = inb(RBR(dev->base_addr));
768*4882a593Smuzhiyun if (msr & RX_FLAG)
769*4882a593Smuzhiyun yam_rx_flag(dev, yp);
770*4882a593Smuzhiyun else
771*4882a593Smuzhiyun yam_rx_byte(dev, yp, rxb);
772*4882a593Smuzhiyun }
773*4882a593Smuzhiyun }
774*4882a593Smuzhiyun }
775*4882a593Smuzhiyun out:
776*4882a593Smuzhiyun return IRQ_RETVAL(handled);
777*4882a593Smuzhiyun }
778*4882a593Smuzhiyun
779*4882a593Smuzhiyun #ifdef CONFIG_PROC_FS
780*4882a593Smuzhiyun
yam_seq_start(struct seq_file * seq,loff_t * pos)781*4882a593Smuzhiyun static void *yam_seq_start(struct seq_file *seq, loff_t *pos)
782*4882a593Smuzhiyun {
783*4882a593Smuzhiyun return (*pos < NR_PORTS) ? yam_devs[*pos] : NULL;
784*4882a593Smuzhiyun }
785*4882a593Smuzhiyun
yam_seq_next(struct seq_file * seq,void * v,loff_t * pos)786*4882a593Smuzhiyun static void *yam_seq_next(struct seq_file *seq, void *v, loff_t *pos)
787*4882a593Smuzhiyun {
788*4882a593Smuzhiyun ++*pos;
789*4882a593Smuzhiyun return (*pos < NR_PORTS) ? yam_devs[*pos] : NULL;
790*4882a593Smuzhiyun }
791*4882a593Smuzhiyun
yam_seq_stop(struct seq_file * seq,void * v)792*4882a593Smuzhiyun static void yam_seq_stop(struct seq_file *seq, void *v)
793*4882a593Smuzhiyun {
794*4882a593Smuzhiyun }
795*4882a593Smuzhiyun
yam_seq_show(struct seq_file * seq,void * v)796*4882a593Smuzhiyun static int yam_seq_show(struct seq_file *seq, void *v)
797*4882a593Smuzhiyun {
798*4882a593Smuzhiyun struct net_device *dev = v;
799*4882a593Smuzhiyun const struct yam_port *yp = netdev_priv(dev);
800*4882a593Smuzhiyun
801*4882a593Smuzhiyun seq_printf(seq, "Device %s\n", dev->name);
802*4882a593Smuzhiyun seq_printf(seq, " Up %d\n", netif_running(dev));
803*4882a593Smuzhiyun seq_printf(seq, " Speed %u\n", yp->bitrate);
804*4882a593Smuzhiyun seq_printf(seq, " IoBase 0x%x\n", yp->iobase);
805*4882a593Smuzhiyun seq_printf(seq, " BaudRate %u\n", yp->baudrate);
806*4882a593Smuzhiyun seq_printf(seq, " IRQ %u\n", yp->irq);
807*4882a593Smuzhiyun seq_printf(seq, " TxState %u\n", yp->tx_state);
808*4882a593Smuzhiyun seq_printf(seq, " Duplex %u\n", yp->dupmode);
809*4882a593Smuzhiyun seq_printf(seq, " HoldDly %u\n", yp->holdd);
810*4882a593Smuzhiyun seq_printf(seq, " TxDelay %u\n", yp->txd);
811*4882a593Smuzhiyun seq_printf(seq, " TxTail %u\n", yp->txtail);
812*4882a593Smuzhiyun seq_printf(seq, " SlotTime %u\n", yp->slot);
813*4882a593Smuzhiyun seq_printf(seq, " Persist %u\n", yp->pers);
814*4882a593Smuzhiyun seq_printf(seq, " TxFrames %lu\n", dev->stats.tx_packets);
815*4882a593Smuzhiyun seq_printf(seq, " RxFrames %lu\n", dev->stats.rx_packets);
816*4882a593Smuzhiyun seq_printf(seq, " TxInt %u\n", yp->nb_mdint);
817*4882a593Smuzhiyun seq_printf(seq, " RxInt %u\n", yp->nb_rxint);
818*4882a593Smuzhiyun seq_printf(seq, " RxOver %lu\n", dev->stats.rx_fifo_errors);
819*4882a593Smuzhiyun seq_printf(seq, "\n");
820*4882a593Smuzhiyun return 0;
821*4882a593Smuzhiyun }
822*4882a593Smuzhiyun
823*4882a593Smuzhiyun static const struct seq_operations yam_seqops = {
824*4882a593Smuzhiyun .start = yam_seq_start,
825*4882a593Smuzhiyun .next = yam_seq_next,
826*4882a593Smuzhiyun .stop = yam_seq_stop,
827*4882a593Smuzhiyun .show = yam_seq_show,
828*4882a593Smuzhiyun };
829*4882a593Smuzhiyun #endif
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun
832*4882a593Smuzhiyun /* --------------------------------------------------------------------- */
833*4882a593Smuzhiyun
yam_open(struct net_device * dev)834*4882a593Smuzhiyun static int yam_open(struct net_device *dev)
835*4882a593Smuzhiyun {
836*4882a593Smuzhiyun struct yam_port *yp = netdev_priv(dev);
837*4882a593Smuzhiyun enum uart u;
838*4882a593Smuzhiyun int i;
839*4882a593Smuzhiyun int ret=0;
840*4882a593Smuzhiyun
841*4882a593Smuzhiyun printk(KERN_INFO "Trying %s at iobase 0x%lx irq %u\n", dev->name, dev->base_addr, dev->irq);
842*4882a593Smuzhiyun
843*4882a593Smuzhiyun if (!yp->bitrate)
844*4882a593Smuzhiyun return -ENXIO;
845*4882a593Smuzhiyun if (!dev->base_addr || dev->base_addr > 0x1000 - YAM_EXTENT ||
846*4882a593Smuzhiyun dev->irq < 2 || dev->irq > 15) {
847*4882a593Smuzhiyun return -ENXIO;
848*4882a593Smuzhiyun }
849*4882a593Smuzhiyun if (!request_region(dev->base_addr, YAM_EXTENT, dev->name))
850*4882a593Smuzhiyun {
851*4882a593Smuzhiyun printk(KERN_ERR "%s: cannot 0x%lx busy\n", dev->name, dev->base_addr);
852*4882a593Smuzhiyun return -EACCES;
853*4882a593Smuzhiyun }
854*4882a593Smuzhiyun if ((u = yam_check_uart(dev->base_addr)) == c_uart_unknown) {
855*4882a593Smuzhiyun printk(KERN_ERR "%s: cannot find uart type\n", dev->name);
856*4882a593Smuzhiyun ret = -EIO;
857*4882a593Smuzhiyun goto out_release_base;
858*4882a593Smuzhiyun }
859*4882a593Smuzhiyun if (fpga_download(dev->base_addr, yp->bitrate)) {
860*4882a593Smuzhiyun printk(KERN_ERR "%s: cannot init FPGA\n", dev->name);
861*4882a593Smuzhiyun ret = -EIO;
862*4882a593Smuzhiyun goto out_release_base;
863*4882a593Smuzhiyun }
864*4882a593Smuzhiyun outb(0, IER(dev->base_addr));
865*4882a593Smuzhiyun if (request_irq(dev->irq, yam_interrupt, IRQF_SHARED, dev->name, dev)) {
866*4882a593Smuzhiyun printk(KERN_ERR "%s: irq %d busy\n", dev->name, dev->irq);
867*4882a593Smuzhiyun ret = -EBUSY;
868*4882a593Smuzhiyun goto out_release_base;
869*4882a593Smuzhiyun }
870*4882a593Smuzhiyun
871*4882a593Smuzhiyun yam_set_uart(dev);
872*4882a593Smuzhiyun
873*4882a593Smuzhiyun netif_start_queue(dev);
874*4882a593Smuzhiyun
875*4882a593Smuzhiyun yp->slotcnt = yp->slot / 10;
876*4882a593Smuzhiyun
877*4882a593Smuzhiyun /* Reset overruns for all ports - FPGA programming makes overruns */
878*4882a593Smuzhiyun for (i = 0; i < NR_PORTS; i++) {
879*4882a593Smuzhiyun struct net_device *yam_dev = yam_devs[i];
880*4882a593Smuzhiyun
881*4882a593Smuzhiyun inb(LSR(yam_dev->base_addr));
882*4882a593Smuzhiyun yam_dev->stats.rx_fifo_errors = 0;
883*4882a593Smuzhiyun }
884*4882a593Smuzhiyun
885*4882a593Smuzhiyun printk(KERN_INFO "%s at iobase 0x%lx irq %u uart %s\n", dev->name, dev->base_addr, dev->irq,
886*4882a593Smuzhiyun uart_str[u]);
887*4882a593Smuzhiyun return 0;
888*4882a593Smuzhiyun
889*4882a593Smuzhiyun out_release_base:
890*4882a593Smuzhiyun release_region(dev->base_addr, YAM_EXTENT);
891*4882a593Smuzhiyun return ret;
892*4882a593Smuzhiyun }
893*4882a593Smuzhiyun
894*4882a593Smuzhiyun /* --------------------------------------------------------------------- */
895*4882a593Smuzhiyun
yam_close(struct net_device * dev)896*4882a593Smuzhiyun static int yam_close(struct net_device *dev)
897*4882a593Smuzhiyun {
898*4882a593Smuzhiyun struct sk_buff *skb;
899*4882a593Smuzhiyun struct yam_port *yp = netdev_priv(dev);
900*4882a593Smuzhiyun
901*4882a593Smuzhiyun if (!dev)
902*4882a593Smuzhiyun return -EINVAL;
903*4882a593Smuzhiyun
904*4882a593Smuzhiyun /*
905*4882a593Smuzhiyun * disable interrupts
906*4882a593Smuzhiyun */
907*4882a593Smuzhiyun outb(0, IER(dev->base_addr));
908*4882a593Smuzhiyun outb(1, MCR(dev->base_addr));
909*4882a593Smuzhiyun /* Remove IRQ handler if last */
910*4882a593Smuzhiyun free_irq(dev->irq,dev);
911*4882a593Smuzhiyun release_region(dev->base_addr, YAM_EXTENT);
912*4882a593Smuzhiyun netif_stop_queue(dev);
913*4882a593Smuzhiyun while ((skb = skb_dequeue(&yp->send_queue)))
914*4882a593Smuzhiyun dev_kfree_skb(skb);
915*4882a593Smuzhiyun
916*4882a593Smuzhiyun printk(KERN_INFO "%s: close yam at iobase 0x%lx irq %u\n",
917*4882a593Smuzhiyun yam_drvname, dev->base_addr, dev->irq);
918*4882a593Smuzhiyun return 0;
919*4882a593Smuzhiyun }
920*4882a593Smuzhiyun
921*4882a593Smuzhiyun /* --------------------------------------------------------------------- */
922*4882a593Smuzhiyun
yam_ioctl(struct net_device * dev,struct ifreq * ifr,int cmd)923*4882a593Smuzhiyun static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
924*4882a593Smuzhiyun {
925*4882a593Smuzhiyun struct yam_port *yp = netdev_priv(dev);
926*4882a593Smuzhiyun struct yamdrv_ioctl_cfg yi;
927*4882a593Smuzhiyun struct yamdrv_ioctl_mcs *ym;
928*4882a593Smuzhiyun int ioctl_cmd;
929*4882a593Smuzhiyun
930*4882a593Smuzhiyun if (copy_from_user(&ioctl_cmd, ifr->ifr_data, sizeof(int)))
931*4882a593Smuzhiyun return -EFAULT;
932*4882a593Smuzhiyun
933*4882a593Smuzhiyun if (yp->magic != YAM_MAGIC)
934*4882a593Smuzhiyun return -EINVAL;
935*4882a593Smuzhiyun
936*4882a593Smuzhiyun if (!capable(CAP_NET_ADMIN))
937*4882a593Smuzhiyun return -EPERM;
938*4882a593Smuzhiyun
939*4882a593Smuzhiyun if (cmd != SIOCDEVPRIVATE)
940*4882a593Smuzhiyun return -EINVAL;
941*4882a593Smuzhiyun
942*4882a593Smuzhiyun switch (ioctl_cmd) {
943*4882a593Smuzhiyun
944*4882a593Smuzhiyun case SIOCYAMRESERVED:
945*4882a593Smuzhiyun return -EINVAL; /* unused */
946*4882a593Smuzhiyun
947*4882a593Smuzhiyun case SIOCYAMSMCS:
948*4882a593Smuzhiyun if (netif_running(dev))
949*4882a593Smuzhiyun return -EINVAL; /* Cannot change this parameter when up */
950*4882a593Smuzhiyun ym = memdup_user(ifr->ifr_data,
951*4882a593Smuzhiyun sizeof(struct yamdrv_ioctl_mcs));
952*4882a593Smuzhiyun if (IS_ERR(ym))
953*4882a593Smuzhiyun return PTR_ERR(ym);
954*4882a593Smuzhiyun if (ym->cmd != SIOCYAMSMCS || ym->bitrate > YAM_MAXBITRATE) {
955*4882a593Smuzhiyun kfree(ym);
956*4882a593Smuzhiyun return -EINVAL;
957*4882a593Smuzhiyun }
958*4882a593Smuzhiyun /* setting predef as 0 for loading userdefined mcs data */
959*4882a593Smuzhiyun add_mcs(ym->bits, ym->bitrate, 0);
960*4882a593Smuzhiyun kfree(ym);
961*4882a593Smuzhiyun break;
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun case SIOCYAMSCFG:
964*4882a593Smuzhiyun if (!capable(CAP_SYS_RAWIO))
965*4882a593Smuzhiyun return -EPERM;
966*4882a593Smuzhiyun if (copy_from_user(&yi, ifr->ifr_data, sizeof(struct yamdrv_ioctl_cfg)))
967*4882a593Smuzhiyun return -EFAULT;
968*4882a593Smuzhiyun
969*4882a593Smuzhiyun if (yi.cmd != SIOCYAMSCFG)
970*4882a593Smuzhiyun return -EINVAL;
971*4882a593Smuzhiyun if ((yi.cfg.mask & YAM_IOBASE) && netif_running(dev))
972*4882a593Smuzhiyun return -EINVAL; /* Cannot change this parameter when up */
973*4882a593Smuzhiyun if ((yi.cfg.mask & YAM_IRQ) && netif_running(dev))
974*4882a593Smuzhiyun return -EINVAL; /* Cannot change this parameter when up */
975*4882a593Smuzhiyun if ((yi.cfg.mask & YAM_BITRATE) && netif_running(dev))
976*4882a593Smuzhiyun return -EINVAL; /* Cannot change this parameter when up */
977*4882a593Smuzhiyun if ((yi.cfg.mask & YAM_BAUDRATE) && netif_running(dev))
978*4882a593Smuzhiyun return -EINVAL; /* Cannot change this parameter when up */
979*4882a593Smuzhiyun
980*4882a593Smuzhiyun if (yi.cfg.mask & YAM_IOBASE) {
981*4882a593Smuzhiyun yp->iobase = yi.cfg.iobase;
982*4882a593Smuzhiyun dev->base_addr = yi.cfg.iobase;
983*4882a593Smuzhiyun }
984*4882a593Smuzhiyun if (yi.cfg.mask & YAM_IRQ) {
985*4882a593Smuzhiyun if (yi.cfg.irq > 15)
986*4882a593Smuzhiyun return -EINVAL;
987*4882a593Smuzhiyun yp->irq = yi.cfg.irq;
988*4882a593Smuzhiyun dev->irq = yi.cfg.irq;
989*4882a593Smuzhiyun }
990*4882a593Smuzhiyun if (yi.cfg.mask & YAM_BITRATE) {
991*4882a593Smuzhiyun if (yi.cfg.bitrate > YAM_MAXBITRATE)
992*4882a593Smuzhiyun return -EINVAL;
993*4882a593Smuzhiyun yp->bitrate = yi.cfg.bitrate;
994*4882a593Smuzhiyun }
995*4882a593Smuzhiyun if (yi.cfg.mask & YAM_BAUDRATE) {
996*4882a593Smuzhiyun if (yi.cfg.baudrate > YAM_MAXBAUDRATE)
997*4882a593Smuzhiyun return -EINVAL;
998*4882a593Smuzhiyun yp->baudrate = yi.cfg.baudrate;
999*4882a593Smuzhiyun }
1000*4882a593Smuzhiyun if (yi.cfg.mask & YAM_MODE) {
1001*4882a593Smuzhiyun if (yi.cfg.mode > YAM_MAXMODE)
1002*4882a593Smuzhiyun return -EINVAL;
1003*4882a593Smuzhiyun yp->dupmode = yi.cfg.mode;
1004*4882a593Smuzhiyun }
1005*4882a593Smuzhiyun if (yi.cfg.mask & YAM_HOLDDLY) {
1006*4882a593Smuzhiyun if (yi.cfg.holddly > YAM_MAXHOLDDLY)
1007*4882a593Smuzhiyun return -EINVAL;
1008*4882a593Smuzhiyun yp->holdd = yi.cfg.holddly;
1009*4882a593Smuzhiyun }
1010*4882a593Smuzhiyun if (yi.cfg.mask & YAM_TXDELAY) {
1011*4882a593Smuzhiyun if (yi.cfg.txdelay > YAM_MAXTXDELAY)
1012*4882a593Smuzhiyun return -EINVAL;
1013*4882a593Smuzhiyun yp->txd = yi.cfg.txdelay;
1014*4882a593Smuzhiyun }
1015*4882a593Smuzhiyun if (yi.cfg.mask & YAM_TXTAIL) {
1016*4882a593Smuzhiyun if (yi.cfg.txtail > YAM_MAXTXTAIL)
1017*4882a593Smuzhiyun return -EINVAL;
1018*4882a593Smuzhiyun yp->txtail = yi.cfg.txtail;
1019*4882a593Smuzhiyun }
1020*4882a593Smuzhiyun if (yi.cfg.mask & YAM_PERSIST) {
1021*4882a593Smuzhiyun if (yi.cfg.persist > YAM_MAXPERSIST)
1022*4882a593Smuzhiyun return -EINVAL;
1023*4882a593Smuzhiyun yp->pers = yi.cfg.persist;
1024*4882a593Smuzhiyun }
1025*4882a593Smuzhiyun if (yi.cfg.mask & YAM_SLOTTIME) {
1026*4882a593Smuzhiyun if (yi.cfg.slottime > YAM_MAXSLOTTIME)
1027*4882a593Smuzhiyun return -EINVAL;
1028*4882a593Smuzhiyun yp->slot = yi.cfg.slottime;
1029*4882a593Smuzhiyun yp->slotcnt = yp->slot / 10;
1030*4882a593Smuzhiyun }
1031*4882a593Smuzhiyun break;
1032*4882a593Smuzhiyun
1033*4882a593Smuzhiyun case SIOCYAMGCFG:
1034*4882a593Smuzhiyun memset(&yi, 0, sizeof(yi));
1035*4882a593Smuzhiyun yi.cfg.mask = 0xffffffff;
1036*4882a593Smuzhiyun yi.cfg.iobase = yp->iobase;
1037*4882a593Smuzhiyun yi.cfg.irq = yp->irq;
1038*4882a593Smuzhiyun yi.cfg.bitrate = yp->bitrate;
1039*4882a593Smuzhiyun yi.cfg.baudrate = yp->baudrate;
1040*4882a593Smuzhiyun yi.cfg.mode = yp->dupmode;
1041*4882a593Smuzhiyun yi.cfg.txdelay = yp->txd;
1042*4882a593Smuzhiyun yi.cfg.holddly = yp->holdd;
1043*4882a593Smuzhiyun yi.cfg.txtail = yp->txtail;
1044*4882a593Smuzhiyun yi.cfg.persist = yp->pers;
1045*4882a593Smuzhiyun yi.cfg.slottime = yp->slot;
1046*4882a593Smuzhiyun if (copy_to_user(ifr->ifr_data, &yi, sizeof(struct yamdrv_ioctl_cfg)))
1047*4882a593Smuzhiyun return -EFAULT;
1048*4882a593Smuzhiyun break;
1049*4882a593Smuzhiyun
1050*4882a593Smuzhiyun default:
1051*4882a593Smuzhiyun return -EINVAL;
1052*4882a593Smuzhiyun
1053*4882a593Smuzhiyun }
1054*4882a593Smuzhiyun
1055*4882a593Smuzhiyun return 0;
1056*4882a593Smuzhiyun }
1057*4882a593Smuzhiyun
1058*4882a593Smuzhiyun /* --------------------------------------------------------------------- */
1059*4882a593Smuzhiyun
yam_set_mac_address(struct net_device * dev,void * addr)1060*4882a593Smuzhiyun static int yam_set_mac_address(struct net_device *dev, void *addr)
1061*4882a593Smuzhiyun {
1062*4882a593Smuzhiyun struct sockaddr *sa = (struct sockaddr *) addr;
1063*4882a593Smuzhiyun
1064*4882a593Smuzhiyun /* addr is an AX.25 shifted ASCII mac address */
1065*4882a593Smuzhiyun memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
1066*4882a593Smuzhiyun return 0;
1067*4882a593Smuzhiyun }
1068*4882a593Smuzhiyun
1069*4882a593Smuzhiyun /* --------------------------------------------------------------------- */
1070*4882a593Smuzhiyun
1071*4882a593Smuzhiyun static const struct net_device_ops yam_netdev_ops = {
1072*4882a593Smuzhiyun .ndo_open = yam_open,
1073*4882a593Smuzhiyun .ndo_stop = yam_close,
1074*4882a593Smuzhiyun .ndo_start_xmit = yam_send_packet,
1075*4882a593Smuzhiyun .ndo_do_ioctl = yam_ioctl,
1076*4882a593Smuzhiyun .ndo_set_mac_address = yam_set_mac_address,
1077*4882a593Smuzhiyun };
1078*4882a593Smuzhiyun
yam_setup(struct net_device * dev)1079*4882a593Smuzhiyun static void yam_setup(struct net_device *dev)
1080*4882a593Smuzhiyun {
1081*4882a593Smuzhiyun struct yam_port *yp = netdev_priv(dev);
1082*4882a593Smuzhiyun
1083*4882a593Smuzhiyun yp->magic = YAM_MAGIC;
1084*4882a593Smuzhiyun yp->bitrate = DEFAULT_BITRATE;
1085*4882a593Smuzhiyun yp->baudrate = DEFAULT_BITRATE * 2;
1086*4882a593Smuzhiyun yp->iobase = 0;
1087*4882a593Smuzhiyun yp->irq = 0;
1088*4882a593Smuzhiyun yp->dupmode = 0;
1089*4882a593Smuzhiyun yp->holdd = DEFAULT_HOLDD;
1090*4882a593Smuzhiyun yp->txd = DEFAULT_TXD;
1091*4882a593Smuzhiyun yp->txtail = DEFAULT_TXTAIL;
1092*4882a593Smuzhiyun yp->slot = DEFAULT_SLOT;
1093*4882a593Smuzhiyun yp->pers = DEFAULT_PERS;
1094*4882a593Smuzhiyun yp->dev = dev;
1095*4882a593Smuzhiyun
1096*4882a593Smuzhiyun dev->base_addr = yp->iobase;
1097*4882a593Smuzhiyun dev->irq = yp->irq;
1098*4882a593Smuzhiyun
1099*4882a593Smuzhiyun skb_queue_head_init(&yp->send_queue);
1100*4882a593Smuzhiyun
1101*4882a593Smuzhiyun dev->netdev_ops = &yam_netdev_ops;
1102*4882a593Smuzhiyun dev->header_ops = &ax25_header_ops;
1103*4882a593Smuzhiyun
1104*4882a593Smuzhiyun dev->type = ARPHRD_AX25;
1105*4882a593Smuzhiyun dev->hard_header_len = AX25_MAX_HEADER_LEN;
1106*4882a593Smuzhiyun dev->mtu = AX25_MTU;
1107*4882a593Smuzhiyun dev->addr_len = AX25_ADDR_LEN;
1108*4882a593Smuzhiyun memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
1109*4882a593Smuzhiyun memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN);
1110*4882a593Smuzhiyun }
1111*4882a593Smuzhiyun
yam_init_driver(void)1112*4882a593Smuzhiyun static int __init yam_init_driver(void)
1113*4882a593Smuzhiyun {
1114*4882a593Smuzhiyun struct net_device *dev;
1115*4882a593Smuzhiyun int i, err;
1116*4882a593Smuzhiyun char name[IFNAMSIZ];
1117*4882a593Smuzhiyun
1118*4882a593Smuzhiyun printk(yam_drvinfo);
1119*4882a593Smuzhiyun
1120*4882a593Smuzhiyun for (i = 0; i < NR_PORTS; i++) {
1121*4882a593Smuzhiyun sprintf(name, "yam%d", i);
1122*4882a593Smuzhiyun
1123*4882a593Smuzhiyun dev = alloc_netdev(sizeof(struct yam_port), name,
1124*4882a593Smuzhiyun NET_NAME_UNKNOWN, yam_setup);
1125*4882a593Smuzhiyun if (!dev) {
1126*4882a593Smuzhiyun pr_err("yam: cannot allocate net device\n");
1127*4882a593Smuzhiyun err = -ENOMEM;
1128*4882a593Smuzhiyun goto error;
1129*4882a593Smuzhiyun }
1130*4882a593Smuzhiyun
1131*4882a593Smuzhiyun err = register_netdev(dev);
1132*4882a593Smuzhiyun if (err) {
1133*4882a593Smuzhiyun printk(KERN_WARNING "yam: cannot register net device %s\n", dev->name);
1134*4882a593Smuzhiyun free_netdev(dev);
1135*4882a593Smuzhiyun goto error;
1136*4882a593Smuzhiyun }
1137*4882a593Smuzhiyun yam_devs[i] = dev;
1138*4882a593Smuzhiyun
1139*4882a593Smuzhiyun }
1140*4882a593Smuzhiyun
1141*4882a593Smuzhiyun timer_setup(&yam_timer, yam_dotimer, 0);
1142*4882a593Smuzhiyun yam_timer.expires = jiffies + HZ / 100;
1143*4882a593Smuzhiyun add_timer(&yam_timer);
1144*4882a593Smuzhiyun
1145*4882a593Smuzhiyun proc_create_seq("yam", 0444, init_net.proc_net, &yam_seqops);
1146*4882a593Smuzhiyun return 0;
1147*4882a593Smuzhiyun error:
1148*4882a593Smuzhiyun while (--i >= 0) {
1149*4882a593Smuzhiyun unregister_netdev(yam_devs[i]);
1150*4882a593Smuzhiyun free_netdev(yam_devs[i]);
1151*4882a593Smuzhiyun }
1152*4882a593Smuzhiyun return err;
1153*4882a593Smuzhiyun }
1154*4882a593Smuzhiyun
1155*4882a593Smuzhiyun /* --------------------------------------------------------------------- */
1156*4882a593Smuzhiyun
yam_cleanup_driver(void)1157*4882a593Smuzhiyun static void __exit yam_cleanup_driver(void)
1158*4882a593Smuzhiyun {
1159*4882a593Smuzhiyun struct yam_mcs *p;
1160*4882a593Smuzhiyun int i;
1161*4882a593Smuzhiyun
1162*4882a593Smuzhiyun del_timer_sync(&yam_timer);
1163*4882a593Smuzhiyun for (i = 0; i < NR_PORTS; i++) {
1164*4882a593Smuzhiyun struct net_device *dev = yam_devs[i];
1165*4882a593Smuzhiyun if (dev) {
1166*4882a593Smuzhiyun unregister_netdev(dev);
1167*4882a593Smuzhiyun free_netdev(dev);
1168*4882a593Smuzhiyun }
1169*4882a593Smuzhiyun }
1170*4882a593Smuzhiyun
1171*4882a593Smuzhiyun while (yam_data) {
1172*4882a593Smuzhiyun p = yam_data;
1173*4882a593Smuzhiyun yam_data = yam_data->next;
1174*4882a593Smuzhiyun kfree(p);
1175*4882a593Smuzhiyun }
1176*4882a593Smuzhiyun
1177*4882a593Smuzhiyun remove_proc_entry("yam", init_net.proc_net);
1178*4882a593Smuzhiyun }
1179*4882a593Smuzhiyun
1180*4882a593Smuzhiyun /* --------------------------------------------------------------------- */
1181*4882a593Smuzhiyun
1182*4882a593Smuzhiyun MODULE_AUTHOR("Frederic Rible F1OAT frible@teaser.fr");
1183*4882a593Smuzhiyun MODULE_DESCRIPTION("Yam amateur radio modem driver");
1184*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1185*4882a593Smuzhiyun MODULE_FIRMWARE(FIRMWARE_1200);
1186*4882a593Smuzhiyun MODULE_FIRMWARE(FIRMWARE_9600);
1187*4882a593Smuzhiyun
1188*4882a593Smuzhiyun module_init(yam_init_driver);
1189*4882a593Smuzhiyun module_exit(yam_cleanup_driver);
1190*4882a593Smuzhiyun
1191*4882a593Smuzhiyun /* --------------------------------------------------------------------- */
1192*4882a593Smuzhiyun
1193