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