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