]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-atmdd.patch
- rel 2; fix for local root hole CVE-2007-4573
[packages/kernel.git] / kernel-atmdd.patch
CommitLineData
c6410bf7 1diff -urN linux-2.4.25/drivers/atm/Makefile linux-2.4.25-atmdd/drivers/atm/Makefile
2--- linux-2.4.25/drivers/atm/Makefile 2004-02-23 15:18:29.000000000 +0100
3+++ linux-2.4.25-atmdd/drivers/atm/Makefile 2004-02-29 22:51:26.000000000 +0100
4@@ -31,6 +31,7 @@
5 endif
6
7 obj-$(CONFIG_ATM_DUMMY) += adummy.o
8+obj-$(CONFIG_ATM_DD) += atmdd.o
9 obj-$(CONFIG_ATM_TCP) += atmtcp.o
10 obj-$(CONFIG_ATM_FIRESTREAM) += firestream.o
11 obj-$(CONFIG_ATM_LANAI) += lanai.o
12diff -urN linux-2.4.25/drivers/atm/Kconfig linux-2.4.25-atmdd/drivers/atm/Kconfig
13--- linux-2.4.25/drivers/atm/Kcnfig 2003-08-25 13:44:41.000000000 +0200
14+++ linux-2.4.25-atmdd/drivers/atm/Kconfig 2004-02-29 22:52:59.000000000 +0100
15@@ -4,6 +4,14 @@
16
17 menu "ATM drivers"
18 depends on NETDEVICES && ATM
19+
20+config ATM_DD
21+ tristate "ATM loopback"
22+ depends on INET && ATM
23+ help
24+ This is an example atm driver. It does not require any actual ATM
25+ hardware. It supports AAL5 and AAL0. Frames are merely looped back
26+ to the sender on the same VC they were sent.
27
28 config ATM_TCP
29 tristate "ATM over TCP"
30diff -urN linux-2.4.25/drivers/atm/atmdd.c linux-2.4.25-atmdd/drivers/atm/atmdd.c
31--- linux-2.4.25/drivers/atm/atmdd.c 1970-01-01 01:00:00.000000000 +0100
32+++ linux-2.4.25-atmdd/drivers/atm/atmdd.c 2004-02-29 22:58:11.000000000 +0100
33@@ -0,0 +1,922 @@
34+/*
35+#######################################################################
36+#
37+# (C) Copyright 2001
38+# Alex Zeffertt, Cambridge Broadband Ltd, ajz@cambridgebroadband.com
39+#
40+# This program is free software; you can redistribute it and/or
41+# modify it under the terms of the GNU General Public License as
42+# published by the Free Software Foundation; either version 2 of
43+# the License, or (at your option) any later version.
44+#
45+# This program is distributed in the hope that it will be useful,
46+# but WITHOUT ANY WARRANTY; without even the implied warranty of
47+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48+# GNU General Public License for more details.
49+#
50+# You should have received a copy of the GNU General Public License
51+# along with this program; if not, write to the Free Software
52+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
53+# MA 02111-1307 USA
54+#######################################################################
55+# Notes:
56+#
57+# This is an example atm driver. It does not require any actual ATM
58+# hardware. It supports AAL5 and AAL0. frames are merely looped back
59+# to the sender on the same VC they were sent.
60+#
61+#######################################################################
62+*/
63+
64+/*############ Includes ###############################################*/
65+
66+#include <linux/module.h>
67+#include <linux/config.h>
68+#include <linux/kernel.h>
69+#include <linux/errno.h>
70+#include <linux/atm.h>
71+#include <linux/atmdev.h>
72+#include <linux/skbuff.h>
73+#include <linux/init.h>
74+#include <linux/netdevice.h>
75+#include <linux/sched.h> /* for xtime */
76+
77+/*############ Defines ################################################*/
78+
79+#define MYATMDD "atmdd"
80+#define KLOG_PREAMBLE MYATMDD ": "
81+#define MYATMDD_VPI_BITS 1 /* Allow ?.1.? but not ?.2.? */
82+#define MYATMDD_VCI_BITS 11 /* Allow ?.?.2047 but not ?.?.2048 */
83+#define MYATMDD_PCR 100000
84+#define RXQ_SZ 16
85+#define TXQ_SZ 16
86+#define AAL5_MTU (1510+8) /* Default AAL5 Maximum Transmission Unit (and length of AAL5 buffers) */
87+#define AAL5_BUFLEN (((AAL5_MTU + 47)/48)*48) /* Round up to n*48 bytes */
88+#if 0
89+# define DEBUG(format,args...) printk(format,##args)
90+#else
91+# define DEBUG(format,args...)
92+#endif
93+/*############ Types ##################################################*/
94+
95+/* status flags shared between s/w and emulated h/w */
96+typedef enum {
97+ RX_EMPTY, /* No sk_buff present */
98+ RX_FULL, /* sk_buff present and awaiting data */
99+ RX_RECVD, /* sk_buff present and contains valid data */
100+} myatmdd_rxstatus_e;
101+
102+/* status flags shared between s/w and emulated h/w */
103+typedef enum {
104+ TX_EMPTY, /* No sk_buff present */
105+ TX_FULL, /* sk_buff present and awaiting transmission */
106+ TX_SENT, /* sk_buff present and has been sent */
107+} myatmdd_txstatus_e;
108+
109+typedef struct {
110+ struct sk_buff **start;
111+ struct sk_buff **end;
112+ struct sk_buff **head;
113+ struct sk_buff **tail;
114+
115+ /* everything below this line emulates h/w */
116+ myatmdd_rxstatus_e *status;
117+ struct sk_buff **hw_ptr;
118+ int *pkt_len;
119+
120+} myatmdd_rxq_t;
121+
122+typedef struct {
123+ struct sk_buff **start;
124+ struct sk_buff **end;
125+ struct sk_buff **head;
126+ struct sk_buff **tail;
127+
128+ /* everything below this line emulates h/w */
129+ myatmdd_txstatus_e *status;
130+ struct sk_buff **hw_ptr;
131+ int *pkt_len;
132+
133+} myatmdd_txq_t;
134+
135+typedef struct {
136+} myatmdd_devdata_t;
137+
138+typedef struct {
139+ myatmdd_rxq_t rxqueue;
140+ myatmdd_txq_t txqueue;
141+} myatmdd_vccdata_t;
142+
143+/*############ Module paramters #######################################*/
144+
145+MODULE_AUTHOR("Alex Zeffertt, ajz@cambridgebroadband.com");
146+MODULE_DESCRIPTION("Example ATM device driver (loopback)");
147+#ifdef MODULE_LICENSE
148+MODULE_LICENSE("GPL");
149+#endif
150+/*#################### Forward declarations ###########################*/
151+
152+static void myatmdd_emulate_loopback_hardware(struct atm_vcc *vcc);
153+
154+static void myatmdd_free_tx_skb(struct sk_buff *skb);
155+
156+/* these functions will need modifying in a real ATM driver */
157+static void myatmdd_rx_interrupt(struct atm_vcc *vcc);
158+static void myatmdd_tx_interrupt(struct atm_vcc *vcc);
159+
160+/* functions for manipulating circular bufs */
161+static int myatmdd_init_rxq(myatmdd_rxq_t *queue, int size);
162+static int myatmdd_init_txq(myatmdd_txq_t *queue, int size);
163+static int myatmdd_release_rxq(myatmdd_rxq_t *queue);
164+static int myatmdd_release_txq(myatmdd_txq_t *queue);
165+static int myatmdd_txq_enqueue(myatmdd_txq_t *queue, struct sk_buff *skb);
166+static int myatmdd_rxq_enqueue(myatmdd_rxq_t *queue, struct sk_buff *skb /* empty buffer */);
167+static struct sk_buff *myatmdd_txq_dequeue(myatmdd_txq_t *queue);
168+static struct sk_buff *myatmdd_rxq_dequeue(myatmdd_rxq_t *queue, int *pkt_len);
169+
170+/* myatmdd_ops registered by ATM device */
171+static int myatmdd_open(struct atm_vcc *vcc);
172+static void myatmdd_close(struct atm_vcc *vcc);
173+static int myatmdd_ioctl(struct atm_dev *dev, unsigned int cmd,void *arg);
174+static int myatmdd_setsockopt(struct atm_vcc *vcc,int level,int optname, void *optval,int optlen);
175+static int myatmdd_getsockopt(struct atm_vcc *vcc,int level,int optname, void *optval,int optlen);
176+static int myatmdd_send(struct atm_vcc *vcc,struct sk_buff *skb);
177+static int myatmdd_change_qos(struct atm_vcc *vcc,struct atm_qos *qos,int flgs);
178+static int myatmdd_proc_read(struct atm_dev *dev,loff_t *pos,char *page);
179+
180+/* myatmdd_phy_ops registered by phy driver */
181+static void myatmdd_phy_int(struct atm_dev *dev);
182+static int myatmdd_phy_start(struct atm_dev *dev); /* <-- This is the only thing exported by PHY driver */
183+static int myatmdd_phy_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg);
184+
185+/*#################### Global scope variables #########################*/
186+
187+/* operations registered by the atm device */
188+static const struct atmdev_ops myatmdd_ops =
189+{
190+ open: myatmdd_open,
191+ close: myatmdd_close,
192+ ioctl: myatmdd_ioctl,
193+ getsockopt: myatmdd_getsockopt,
194+ setsockopt: myatmdd_setsockopt,
195+ send: myatmdd_send,
196+ change_qos: myatmdd_change_qos,
197+ proc_read: myatmdd_proc_read,
198+ owner: THIS_MODULE,
199+};
200+
201+/* operations registered by the phy driver */
202+static const struct atmphy_ops myatmdd_phy_ops = {
203+ start: myatmdd_phy_start,
204+ ioctl: myatmdd_phy_ioctl,
205+ interrupt: myatmdd_phy_int,
206+};
207+
208+struct atm_dev *myatmdd_dev;
209+
210+/*#################### Function definitions ###########################*/
211+
212+
213+/*
214+#########################################################
215+#
216+# Function : myatmdd_rx_interrupt, and myatmdd_tx_interrupt
217+#
218+# Purpose : handle interrupt from hardware. In first
219+# case this means extract recvd buffers and pass
220+# it up protocol stack. In 2nd case this means
221+# free the sent buffers.
222+#
223+# Args : pointer to private data of the VCC concerned
224+#
225+# Returns : nowt
226+#
227+# Notes :
228+#
229+##########################################################
230+# Edit history:
231+# Who When What
232+# AJZ 10Apr03 Created
233+##########################################################
234+*/
235+
236+static void myatmdd_rx_interrupt(struct atm_vcc *vcc)
237+{
238+ struct sk_buff *skb;
239+ myatmdd_vccdata_t *priv = vcc->dev_data;
240+ int pkt_len;
241+
242+ DEBUG("%s\n", __FUNCTION__);
243+
244+ while ((skb = myatmdd_rxq_dequeue(&priv->rxqueue, &pkt_len)))
245+ {
246+ struct sk_buff *newskb;
247+ struct timeval stamp;
248+
249+ /* Get a new skb to replace the one just consumed */
250+ if (!(newskb = dev_alloc_skb(AAL5_BUFLEN)))
251+ {
252+ atomic_inc(&vcc->stats->rx_err);
253+ printk(KERN_ERR KLOG_PREAMBLE "cannot receive packet - out of memory\n");
254+ /* put skb back in rx queue) */
255+ myatmdd_rxq_enqueue(&priv->rxqueue, skb);
256+ return;
257+ }
258+ myatmdd_rxq_enqueue(&priv->rxqueue, newskb);
259+
260+ if (!atm_charge (vcc, skb->truesize))
261+ {
262+ /* Exceeded memory quota for this vcc
263+ * NOTE: if atm_charge succeeds you must then push or accounting will screw up
264+ */
265+ dev_kfree_skb(skb);
266+ /* &vcc->stats->drop stats incremented in atm_charge */
267+ }
268+ else
269+ {
270+ /* sk_buff passed all sanity checks! */
271+
272+ /* Add received length to socket buffer */
273+ skb_put(skb, pkt_len);
274+
275+ /* update device stats */
276+ atomic_inc(&vcc->stats->rx);
277+
278+ /* add timestamp for upper layers to use */
279+ do_gettimeofday(&stamp);
280+ skb_set_timestamp(skb, &stamp);
281+
282+ /* Point socket buffer at the right VCC before giving to socket layer */
283+ ATM_SKB(skb)->vcc = vcc;
284+
285+ /* push socket buffer up to ATM layer */
286+ vcc->push(vcc, skb);
287+ }
288+ }
289+}
290+
291+static void myatmdd_tx_interrupt(struct atm_vcc *vcc)
292+{
293+ struct sk_buff *skb;
294+ myatmdd_vccdata_t *priv = vcc->dev_data;
295+
296+ DEBUG("%s\n", __FUNCTION__);
297+
298+ while ((skb = myatmdd_txq_dequeue(&priv->txqueue)))
299+ {
300+ // Update channel stats and free the memory
301+ atomic_inc(&vcc->stats->tx);
302+ myatmdd_free_tx_skb(skb);
303+ }
304+}
305+
306+/*
307+#########################################################
308+#
309+# Function : myatmdd_emulate_loopback_hardware
310+#
311+# Purpose : emulate things normally done by hardware
312+# i.e. copying tx bufs to rx bufs (we're modelling
313+# a loopback system here), calling the tx done
314+# interrupt, and calling the rx done interrupt.
315+#
316+# Args : priv = data private to VCC
317+#
318+# Returns : nowt
319+#
320+# Notes :
321+#
322+##########################################################
323+# Edit history:
324+# Who When What
325+# AJZ 10Apr03 Created
326+##########################################################
327+*/
328+static void myatmdd_emulate_loopback_hardware(struct atm_vcc *vcc)
329+{
330+ myatmdd_vccdata_t *priv = vcc->dev_data;
331+ struct sk_buff **ptxskb;
332+ struct sk_buff **prxskb;
333+
334+ DEBUG("%s\n", __FUNCTION__);
335+
336+ ptxskb = priv->txqueue.hw_ptr;
337+ prxskb = priv->rxqueue.hw_ptr;
338+
339+ /* Send each tx buff waiting to go */
340+ while (priv->txqueue.status[ptxskb - priv->txqueue.start] == TX_FULL)
341+ {
342+ struct sk_buff *txskb = *ptxskb;
343+ struct sk_buff *rxskb = *prxskb;
344+ int pkt_len = priv->txqueue.pkt_len[ptxskb - priv->txqueue.start];
345+
346+ /* Is there an rx buffer? */
347+ if (priv->rxqueue.status[prxskb - priv->rxqueue.start] == RX_FULL)
348+ {
349+ /* Yes - Is the length in range? */
350+ if (pkt_len <= AAL5_BUFLEN)
351+ {
352+ /* Yes - do the copy */
353+ memcpy(rxskb->data, txskb->data,pkt_len);
354+ priv->rxqueue.pkt_len[prxskb - priv->rxqueue.start] = pkt_len;
355+
356+ /* Indicate rx buffer recvd */
357+ priv->rxqueue.status[prxskb - priv->rxqueue.start] = RX_RECVD;
358+
359+ /* increment and maybe wrap rx pointer */
360+ if (++prxskb == priv->rxqueue.end)
361+ prxskb = priv->rxqueue.start;
362+ priv->rxqueue.hw_ptr = prxskb;
363+ }
364+ else
365+ {
366+ /* No - then h/w cannot do a recv */
367+ printk(KERN_ERR KLOG_PREAMBLE "recvd frame too long - discarded\n");
368+ }
369+ }
370+ else
371+ {
372+ /* No - then h/w cannot do a recv */
373+ printk(KERN_ERR KLOG_PREAMBLE "no rx buffers available\n");
374+ }
375+
376+ /* Indicate tx buffer sent */
377+ priv->txqueue.status[ptxskb - priv->txqueue.start] = TX_SENT;
378+
379+ /* increment and maybe wrap tx pointer */
380+ if (++ptxskb == priv->txqueue.end)
381+ ptxskb = priv->txqueue.start;
382+ priv->txqueue.hw_ptr = ptxskb;
383+
384+ /* Call tx ring interrupt handler */
385+ myatmdd_tx_interrupt(vcc);
386+
387+ /* Call tx ring interrupt handler */
388+ myatmdd_rx_interrupt(vcc);
389+ }
390+}
391+
392+/*
393+#########################################################
394+#
395+# Function : functions for manipulating circular buffs
396+#
397+# Purpose :
398+#
399+# Args :
400+#
401+# Returns :
402+#
403+# Notes :
404+#
405+##########################################################
406+# Edit history:
407+# Who When What
408+# AJZ 10Apr03 Created
409+##########################################################
410+*/
411+
412+static int myatmdd_init_rxq(myatmdd_rxq_t *queue, int size)
413+{
414+ /* TODO - cope with kmalloc failure */
415+ struct sk_buff **pskb;
416+ int i;
417+
418+ DEBUG("%s\n", __FUNCTION__);
419+ queue->hw_ptr = queue->head = queue->tail =
420+ queue->start = kmalloc(size * sizeof(struct sk_buff *), GFP_KERNEL);
421+ queue->end = &queue->start[size];
422+ for (pskb = queue->start; pskb < queue->end; pskb++)
423+ *pskb = NULL;
424+
425+ queue->status = kmalloc(size * sizeof(myatmdd_rxstatus_e),GFP_KERNEL);
426+ for (i = 0; i < size; i++)
427+ queue->status[i] = RX_EMPTY;
428+
429+ queue->pkt_len = kmalloc(size * sizeof(int),GFP_KERNEL);
430+ for (i = 0; i < size; i++)
431+ queue->pkt_len[i] = 0;
432+
433+ return 0;
434+}
435+
436+static int myatmdd_init_txq(myatmdd_txq_t *queue, int size)
437+{
438+ /* TODO - cope with kmalloc failure */
439+ struct sk_buff **pskb;
440+ int i;
441+
442+ DEBUG("%s\n", __FUNCTION__);
443+ queue->hw_ptr = queue->head = queue->tail =
444+ queue->start = kmalloc(size * sizeof(struct sk_buff *), GFP_KERNEL);
445+ queue->end = &queue->start[size];
446+ for (pskb = queue->start; pskb < queue->end; pskb++)
447+ *pskb = NULL;
448+
449+ queue->status = kmalloc(size * sizeof(myatmdd_rxstatus_e),GFP_KERNEL);
450+ for (i = 0; i < size; i++)
451+ queue->status[i] = TX_EMPTY;
452+
453+ queue->pkt_len = kmalloc(size * sizeof(int),GFP_KERNEL);
454+ for (i = 0; i < size; i++)
455+ queue->pkt_len[i] = 0;
456+
457+ return 0;
458+}
459+
460+static int myatmdd_release_rxq(myatmdd_rxq_t *queue)
461+{
462+ struct sk_buff **pskb;
463+
464+ DEBUG("%s\n", __FUNCTION__);
465+ for (pskb = queue->start; pskb < queue->end; pskb++)
466+ {
467+ /* Is there an skb here */
468+ if (*pskb == NULL)
469+ continue; /* No, so skip this entry in ring */
470+
471+ /* Yes - free it */
472+ dev_kfree_skb(*pskb);
473+ }
474+ kfree(queue->start);
475+ kfree(queue->status);
476+ kfree(queue->pkt_len);
477+
478+ return 0;
479+}
480+
481+static int myatmdd_release_txq(myatmdd_txq_t *queue)
482+{
483+ struct sk_buff **pskb;
484+
485+ DEBUG("%s\n", __FUNCTION__);
486+ /* Scan through all TX bd's and cleanup */
487+ for (pskb = queue->start; pskb < queue->end; pskb++)
488+ {
489+ /* Is this buffer currently unused - i.e. no skb */
490+ if (*pskb == NULL)
491+ continue; /* Yes, so ignore it */
492+
493+ /* If we reach here, we have found a socket buffer that
494+ * exists in the TX ring and is waiting to be released.
495+ */
496+ printk(KERN_WARNING KLOG_PREAMBLE "discarding unsent tx sk_buff\n");
497+ atomic_inc(&ATM_SKB(*pskb)->vcc->stats->tx_err);
498+ myatmdd_free_tx_skb(*pskb);
499+ }
500+ kfree(queue->start);
501+ kfree(queue->status);
502+ kfree(queue->pkt_len);
503+
504+ return 0;
505+}
506+
507+/* returns non-zero for "out of space" */
508+static int myatmdd_txq_enqueue(myatmdd_txq_t *queue, struct sk_buff *skb)
509+{
510+ /* increment head and wrap */
511+ struct sk_buff **newhead = queue->head + 1;
512+ if (newhead == queue->end)
513+ newhead = queue->start;
514+
515+ DEBUG("%s\n", __FUNCTION__);
516+
517+ /* abort if tx ring full */
518+ if (newhead == queue->tail)
519+ return -1;
520+
521+ /* all is okay if we're here */
522+ *queue->head = skb;
523+ /* Tell hardware there's a buffer to send */
524+ queue->status[queue->head - queue->start] = TX_FULL;
525+ queue->pkt_len[queue->head - queue->start] = skb->len;
526+ queue->head = newhead;
527+ return 0;
528+}
529+
530+/* returns non-zero for "out of space" */
531+static int myatmdd_rxq_enqueue(myatmdd_rxq_t *queue, struct sk_buff *skb /* empty buffer */)
532+{
533+ /* increment head and wrap */
534+ struct sk_buff **newhead = queue->head + 1;
535+ if (newhead == queue->end)
536+ newhead = queue->start;
537+
538+ DEBUG("%s\n", __FUNCTION__);
539+
540+ /* abort if rx ring full */
541+ if (newhead == queue->tail)
542+ return -1;
543+
544+ /* all is okay if we're here */
545+ *queue->head = skb;
546+ /* Tell hardware there's a buffer to send */
547+ queue->status[queue->head - queue->start] = RX_FULL;
548+ queue->head = newhead;
549+ return 0;
550+}
551+
552+static struct sk_buff *myatmdd_txq_dequeue(myatmdd_txq_t *queue)
553+{
554+ DEBUG("%s\n", __FUNCTION__);
555+ if (queue->tail != queue->head && queue->status[queue->tail - queue->start] == TX_SENT)
556+ {
557+ struct sk_buff *skb = *queue->tail;
558+
559+ /* increment tail and wrap */
560+ struct sk_buff **newtail = queue->tail + 1;
561+ if (newtail == queue->end)
562+ newtail = queue->start;
563+ *queue->tail = NULL;
564+ queue->status[queue->tail - queue->start] = TX_EMPTY;
565+ queue->tail = newtail;
566+ return skb;
567+ }
568+ return NULL;
569+}
570+
571+/* returns NULL for "no new recvd frames" */
572+static struct sk_buff *myatmdd_rxq_dequeue(myatmdd_rxq_t *queue, int *pkt_len)
573+{
574+ DEBUG("%s\n", __FUNCTION__);
575+ if (queue->tail != queue->head && queue->status[queue->tail - queue->start] == RX_RECVD)
576+ {
577+ struct sk_buff *skb = *queue->tail;
578+
579+ /* increment tail and wrap */
580+ struct sk_buff **newtail = queue->tail + 1;
581+ if (newtail == queue->end)
582+ newtail = queue->start;
583+ *queue->tail = NULL;
584+ queue->status[queue->tail - queue->start] = RX_EMPTY;
585+ *pkt_len = queue->pkt_len[queue->tail - queue->start];
586+ queue->tail = newtail;
587+ return skb;
588+ }
589+ return NULL;
590+}
591+
592+/*
593+#########################################################
594+#
595+# Functions : Implementations of function ptrs in
596+# myatmdd_phy_ops. This is the phy driver
597+# start: myatmdd_phy_start,
598+# ioctl: myatmdd_phy_ioctl,
599+# interrupt: myatmdd_phy_int,
600+#
601+# Purpose : See ATM device driver interface v0.1
602+#
603+# Notes : Conforming to Linux ATM device driver i/f
604+# interface. Draft version 0.1
605+#
606+# Designed to work with multiple devices
607+##########################################################
608+# Edit history:
609+# Who When What
610+# AJZ 10Apr03 Created
611+##########################################################
612+*/
613+static int myatmdd_phy_start(struct atm_dev *dev)
614+{
615+ /* Provide ATM driver with a pointer via which it
616+ * may invoke PHY driver's IOCTL or interrupt
617+ * handlers.
618+ */
619+ dev->phy = &myatmdd_phy_ops;
620+
621+ /* If required allocate phy private data and save
622+ * pointer in dev->phy_data;
623+ */
624+
625+ /* TODO Initialise PHY hardware... */
626+
627+ return 0;
628+}
629+
630+/* Should be called by SAR driver when it needs to handle an interrupt
631+ * triggered by PHY.
632+ */
633+static void myatmdd_phy_int(struct atm_dev *dev)
634+{
635+ /* Handle interrupt triggered by PHY */
636+}
637+
638+/* Gets called by SAR driver IOCTL handler for IOCTLS it doesn't recognise */
639+static int myatmdd_phy_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg)
640+{
641+ switch (cmd)
642+ {
643+// case SONET_GETSTATZ:
644+ default:
645+ return -EINVAL;
646+ }
647+}
648+
649+/*
650+#########################################################
651+#
652+# Function : myatmdd_free_tx_skb
653+#
654+# Purpose : frees an sk_buff.
655+#
656+# Args : skb=pointer to socket buffer
657+#
658+# Notes : Tries to use the upper layer pop() function
659+# but uses dev_kfree_skb() if this doesn't exist
660+##########################################################
661+# Edit history:
662+# Who When What
663+# AJZ 10Apr03 Created
664+##########################################################
665+*/
666+static void myatmdd_free_tx_skb(struct sk_buff *skb)
667+{
668+ struct atm_vcc *vcc;
669+
670+ DEBUG("%s\n", __FUNCTION__);
671+
672+ /* See if we can use the VCC pop function */
673+ if (((vcc = ATM_SKB(skb)->vcc) != NULL) && (vcc->pop != NULL))
674+ {
675+ /* Yes, so use ATM socket layer pop function */
676+ vcc->pop(vcc, skb);
677+ }
678+ else
679+ {
680+ printk(KERN_WARNING KLOG_PREAMBLE "unable to call skb free function\n");
681+ /* No, so free socket buffer */
682+ dev_kfree_skb(skb);
683+ }
684+}
685+
686+/*
687+#########################################################
688+#
689+# Functions : Implementations of function ptrs in
690+# myatmdd_ops.
691+# myatmdd_open(),
692+# myatmdd_close(),
693+# myatmdd_ioctl(),
694+# myatmdd_getsockopt(),
695+# myatmdd_setsockopt(),
696+# myatmdd_send(),
697+# myatmdd_sg_send(),
698+# myatmdd_change_qos(),
699+# myatmdd_proc_read()
700+#
701+#
702+# Purpose : See ATM device driver interface v0.1
703+#
704+# Notes : Conforming to Linux ATM device driver i/f
705+# interface. Draft version 0.1
706+#
707+# Designed to work with multiple devices
708+##########################################################
709+# Edit history:
710+# Who When What
711+# AJZ 10Apr03 Created
712+##########################################################
713+*/
714+static int myatmdd_open(struct atm_vcc *vcc)
715+{
716+ myatmdd_vccdata_t *priv;
717+ int i;
718+
719+ DEBUG("%s\n", __FUNCTION__);
720+
721+ /* Make sure we are opening a AAL0 or AAL5 connection */
722+ if ((vcc->qos.aal != ATM_AAL5) && (vcc->qos.aal != ATM_AAL0))
723+ {
724+ printk(KERN_WARNING KLOG_PREAMBLE "invalid AAL\n");
725+ return -EINVAL;
726+ }
727+
728+ /* Address is in use */
729+ set_bit(ATM_VF_ADDR, &vcc->flags);
730+
731+ /* Allocate some vcc-private memory */
732+ vcc->dev_data = kmalloc(sizeof(myatmdd_vccdata_t), GFP_KERNEL);
733+ if (vcc->dev_data == NULL)
734+ return -ENOMEM;
735+ priv = vcc->dev_data;
736+
737+ /* Setup the hardware for new VC... */
738+
739+ /* Do not allow half open VCs - otherwise the example driver will not be able
740+ * to loop back frames sent !
741+ */
742+ if (vcc->qos.rxtp.traffic_class == ATM_NONE || vcc->qos.txtp.traffic_class == ATM_NONE)
743+ {
744+ kfree(vcc->dev_data);
745+ return -EPERM;
746+ }
747+
748+ /* Create rx/tx queues for this VC */
749+ myatmdd_init_txq(&priv->txqueue, TXQ_SZ);
750+ myatmdd_init_rxq(&priv->rxqueue, RXQ_SZ);
751+
752+ /* Fill rx queue with empty skbuffs */
753+ for (i = 0 ; i < RXQ_SZ - 1; i++)
754+ {
755+ struct sk_buff *skb = dev_alloc_skb(AAL5_BUFLEN);
756+ myatmdd_rxq_enqueue(&priv->rxqueue,skb);
757+ }
758+
759+ /* Connection is now ready to receive data */
760+ set_bit(ATM_VF_READY, &vcc->flags);
761+
762+ return 0;
763+}
764+
765+static void myatmdd_close(struct atm_vcc *vcc)
766+{
767+ myatmdd_vccdata_t *priv = vcc->dev_data;
768+
769+ DEBUG("%s\n", __FUNCTION__);
770+
771+ /* Indicate channel closed */
772+ clear_bit(ATM_VF_READY, &vcc->flags);
773+
774+ /* TODO Uninitialise the hardware for this VC... */
775+
776+ /* empty the rx and tx queues */
777+ myatmdd_release_txq(&priv->txqueue);
778+ myatmdd_release_rxq(&priv->rxqueue);
779+
780+ /* Free the vcc-private memory */
781+ kfree(vcc->dev_data);
782+}
783+
784+static int myatmdd_ioctl(struct atm_dev *dev, unsigned int cmd,void *arg)
785+{
786+ /* myatmdd does not currently have an ioctl interface so pass ioctl onto PHY */
787+ if (dev->phy && dev->phy->ioctl) {
788+ return dev->phy->ioctl(dev, cmd, arg);
789+ }
790+ return -EINVAL;
791+}
792+
793+static int myatmdd_getsockopt(struct atm_vcc *vcc,int level,int optname, void *optval,int optlen)
794+{
795+ return -EINVAL;
796+}
797+
798+static int myatmdd_setsockopt(struct atm_vcc *vcc,int level,int optname, void *optval,int optlen)
799+{
800+ return -EINVAL;
801+}
802+
803+/* Note may be called in either process or interrupt context! */
804+static int myatmdd_send(struct atm_vcc *vcc,struct sk_buff *skb)
805+{
806+ myatmdd_vccdata_t *priv = vcc->dev_data;
807+
808+ DEBUG("%s\n", __FUNCTION__);
809+
810+ /* Assign VCC to socket buffer
811+ * Note: this must be done before attempting to call
812+ * myatmdd_free_tx_skb() as this may use ATM_SKB(skb)->vcc->pop()
813+ */
814+ ATM_SKB(skb)->vcc = vcc;
815+
816+ /* Setup hardware to send and arrange callback of myatmdd_send_complete... */
817+
818+ /* In this example ATM device driver all VCs are looped back.
819+ * So copy to the rxq and emulate an rx interrupt
820+ */
821+
822+ /* Can we accept another skb to send ? */
823+ if (myatmdd_txq_enqueue(&priv->txqueue, skb))
824+ {
825+ /* No - free socket buffer */
826+ myatmdd_free_tx_skb(skb);
827+
828+ /* Update tx channel stats */
829+ atomic_inc(&vcc->stats->tx_err);
830+
831+ /* Tell protocol layer to back off */
832+ return(-EBUSY);
833+ }
834+
835+ /* This is the bit which copies the tx ring to the rx ring,
836+ * and triggers emulated rx and tx interrupts
837+ */
838+ myatmdd_emulate_loopback_hardware(vcc);
839+
840+ return 0;
841+}
842+
843+static int myatmdd_change_qos(struct atm_vcc *vcc,struct atm_qos *qos,int flgs)
844+{
845+ return 0;
846+}
847+
848+static int myatmdd_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
849+{
850+ int left = (int) *pos;
851+
852+ if (!left--)
853+ return sprintf(page, "1st line of stats\n");
854+ if (!left--)
855+ return sprintf(page, "2nd line of stats\n");
856+ if (!left--)
857+ return sprintf(page, "3rd line of stats\n");
858+
859+ return 0;
860+}
861+
862+/*
863+#########################################################
864+#
865+# Function : myatmdd_init
866+#
867+# Purpose : init the module, init and register the ATM device
868+#
869+# Args : none
870+#
871+# Returns : return code
872+#
873+# Notes :
874+#
875+##########################################################
876+# Edit history:
877+# Who When What
878+# AJZ 10Apr03 Created
879+##########################################################
880+*/
881+int __init myatmdd_init(void)
882+{
883+ myatmdd_devdata_t *priv = kmalloc(sizeof(myatmdd_devdata_t),GFP_KERNEL);
884+
885+ if (priv == NULL)
886+ return -ENOMEM;
887+
888+ /* Register the new device */
889+ myatmdd_dev = atm_dev_register(MYATMDD,&myatmdd_ops,-1,NULL);
890+
891+ /* Were we able to register this device? */
892+ if (myatmdd_dev == NULL)
893+ {
894+ printk(KERN_ERR KLOG_PREAMBLE "failed to register CPM ATM device\n");
895+ return -EPERM;
896+ }
897+
898+ /* Save pointer to device private data */
899+ myatmdd_dev->dev_data = priv;
900+
901+ /* Initialise device parameters */
902+ myatmdd_dev->ci_range.vpi_bits = MYATMDD_VPI_BITS;
903+ myatmdd_dev->ci_range.vci_bits = MYATMDD_VCI_BITS;
904+ myatmdd_dev->link_rate = MYATMDD_PCR;
905+
906+ /* Set up phy device */
907+ myatmdd_phy_start(myatmdd_dev);
908+
909+ /* TODO Initialise SAR hardware... */
910+
911+ /* Console output */
912+ printk(KERN_INFO KLOG_PREAMBLE "Initialised\n");
913+
914+ return 0;
915+}
916+
917+/* NOTE:
918+ * module_init() is called by insmod, if built as module,
919+ * or by do_initcalls(), if built as a resident driver.
920+ */
921+module_init(myatmdd_init);
922+
923+/*
924+#########################################################
925+#
926+# Function : myatmdd_exit
927+#
928+# Purpose : delete module, uninit and dereg ATM device
929+#
930+# Args : none
931+#
932+# Returns : none
933+#
934+# Notes :
935+#
936+##########################################################
937+# Edit history:
938+# Who When What
939+# AJZ 10Apr03 Created
940+##########################################################
941+*/
942+
943+#ifdef MODULE
944+static void __exit myatmdd_exit(void)
945+{
946+ /* Disable SAR hardware... */
947+
948+ /* Console output */
949+ printk(KERN_ERR KLOG_PREAMBLE "Uninitialised\n");
950+ kfree(myatmdd_dev->dev_data);
951+ atm_dev_deregister(myatmdd_dev);
952+}
953+module_exit(myatmdd_exit);
954+
955+#endif /* MODULE */
This page took 0.132229 seconds and 4 git commands to generate.