* better
[mascara-docs.git] / i386 / linux-2.3.21 / drivers / atm / atmtcp.c
blobedd2ea1ccdc257f76198349ab7f4cef5d245f583
1 /* drivers/atm/atmtcp.c - ATM over TCP "device" driver */
3 /* Written 1997-1999 by Werner Almesberger, EPFL LRC/ICA */
6 #include <linux/module.h>
7 #include <linux/wait.h>
8 #include <linux/atmdev.h>
9 #include <linux/atm_tcp.h>
10 #include <asm/uaccess.h>
11 #include "../../net/atm/protocols.h" /* @@@ fix this */
14 #define PRIV(dev) ((struct atmtcp_dev_data *) ((dev)->dev_data))
17 struct atmtcp_dev_data {
18 struct atm_vcc *vcc; /* control VCC; NULL if detached */
19 int persist; /* non-zero if persistent */
23 #define DEV_LABEL "atmtcp"
25 #define MAX_VPI_BITS 8 /* simplifies life */
26 #define MAX_VCI_BITS 16
30 * Hairy code ahead: the control VCC may be closed while we're still
31 * waiting for an answer, so we need to re-validate out_vcc every once
32 * in a while.
36 static int atmtcp_send_control(struct atm_vcc *vcc,int type,
37 const struct atmtcp_control *msg,unsigned short flag)
39 struct atm_vcc *out_vcc;
40 struct sk_buff *skb;
41 struct atmtcp_control *new_msg;
42 unsigned short old_flags;
44 out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL;
45 if (!out_vcc) return -EUNATCH;
46 skb = alloc_skb(sizeof(*msg),GFP_KERNEL);
47 if (!skb) return -ENOMEM;
48 mb();
49 out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL;
50 if (!out_vcc) {
51 dev_kfree_skb(skb);
52 return -EUNATCH;
54 atm_force_charge(out_vcc,skb->truesize);
55 new_msg = (struct atmtcp_control *) skb_put(skb,sizeof(*new_msg));
56 *new_msg = *msg;
57 new_msg->hdr.length = ATMTCP_HDR_MAGIC;
58 new_msg->type = type;
59 new_msg->vcc = (unsigned long) vcc;
60 old_flags = vcc->flags;
61 out_vcc->push(out_vcc,skb);
62 while (!((vcc->flags ^ old_flags) & flag)) {
63 mb();
64 out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL;
65 if (!out_vcc) return -EUNATCH;
66 sleep_on(&vcc->sleep);
69 return 0;
73 static int atmtcp_recv_control(const struct atmtcp_control *msg)
75 struct atm_vcc *vcc = (struct atm_vcc *) msg->vcc;
77 vcc->vpi = msg->addr.sap_addr.vpi;
78 vcc->vci = msg->addr.sap_addr.vci;
79 vcc->qos = msg->qos;
80 vcc->reply = msg->result;
81 switch (msg->type) {
82 case ATMTCP_CTRL_OPEN:
83 vcc->flags ^= ATM_VF_READY;
84 break;
85 case ATMTCP_CTRL_CLOSE:
86 vcc->flags ^= ATM_VF_ADDR;
87 break;
88 default:
89 printk(KERN_ERR "atmtcp_recv_control: unknown type %d\n",
90 msg->type);
91 return -EINVAL;
93 wake_up(&vcc->sleep);
94 return 0;
98 static void atmtcp_v_dev_close(struct atm_dev *dev)
100 MOD_DEC_USE_COUNT;
104 static int atmtcp_v_open(struct atm_vcc *vcc,short vpi,int vci)
106 struct atmtcp_control msg;
107 int error;
109 memset(&msg,0,sizeof(msg));
110 msg.addr.sap_family = AF_ATMPVC;
111 msg.hdr.vpi = htons(vpi);
112 msg.addr.sap_addr.vpi = vpi;
113 msg.hdr.vci = htons(vci);
114 msg.addr.sap_addr.vci = vci;
115 error = atm_find_ci(vcc,&msg.addr.sap_addr.vpi,&msg.addr.sap_addr.vci);
116 if (error) return error;
117 if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) return 0;
118 msg.type = ATMTCP_CTRL_OPEN;
119 msg.qos = vcc->qos;
120 vcc->flags |= ATM_VF_ADDR;
121 vcc->flags &= ~ATM_VF_READY; /* just in case ... */
122 error = atmtcp_send_control(vcc,ATMTCP_CTRL_OPEN,&msg,ATM_VF_READY);
123 if (error) return error;
124 return vcc->reply;
128 static void atmtcp_v_close(struct atm_vcc *vcc)
130 struct atmtcp_control msg;
132 memset(&msg,0,sizeof(msg));
133 msg.addr.sap_family = AF_ATMPVC;
134 msg.addr.sap_addr.vpi = vcc->vpi;
135 msg.addr.sap_addr.vci = vcc->vci;
136 vcc->flags &= ~ATM_VF_READY;
137 (void) atmtcp_send_control(vcc,ATMTCP_CTRL_CLOSE,&msg,ATM_VF_ADDR);
141 static int atmtcp_v_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg)
143 struct atm_cirange ci;
144 struct atm_vcc *vcc;
146 if (cmd != ATM_SETCIRANGE) return -EINVAL;
147 if (copy_from_user(&ci,(void *) arg,sizeof(ci))) return -EFAULT;
148 if (ci.vpi_bits == ATM_CI_MAX) ci.vpi_bits = MAX_VPI_BITS;
149 if (ci.vci_bits == ATM_CI_MAX) ci.vci_bits = MAX_VCI_BITS;
150 if (ci.vpi_bits > MAX_VPI_BITS || ci.vpi_bits < 0 ||
151 ci.vci_bits > MAX_VCI_BITS || ci.vci_bits < 0) return -EINVAL;
152 for (vcc = dev->vccs; vcc; vcc = vcc->next)
153 if ((vcc->vpi >> ci.vpi_bits) ||
154 (vcc->vci >> ci.vci_bits)) return -EBUSY;
155 dev->ci_range = ci;
156 return 0;
160 static int atmtcp_v_send(struct atm_vcc *vcc,struct sk_buff *skb)
162 struct atmtcp_dev_data *dev_data;
163 struct atm_vcc *out_vcc;
164 struct sk_buff *new_skb;
165 struct atmtcp_hdr *hdr;
166 int size;
168 dev_data = PRIV(vcc->dev);
169 if (dev_data) out_vcc = dev_data->vcc;
170 if (!dev_data || !out_vcc) {
171 if (vcc->pop) vcc->pop(vcc,skb);
172 else dev_kfree_skb(skb);
173 if (dev_data) return 0;
174 vcc->stats->tx_err++;
175 return -ENOLINK;
177 size = skb->len+sizeof(struct atmtcp_hdr);
178 new_skb = atm_alloc_charge(out_vcc,size,GFP_ATOMIC);
179 if (!new_skb) {
180 if (vcc->pop) vcc->pop(vcc,skb);
181 else dev_kfree_skb(skb);
182 vcc->stats->tx_err++;
183 return -ENOBUFS;
185 hdr = (void *) skb_put(new_skb,sizeof(struct atmtcp_hdr));
186 hdr->vpi = htons(vcc->vpi);
187 hdr->vci = htons(vcc->vci);
188 hdr->length = htonl(skb->len);
189 memcpy(skb_put(new_skb,skb->len),skb->data,skb->len);
190 if (vcc->pop) vcc->pop(vcc,skb);
191 else dev_kfree_skb(skb);
192 out_vcc->push(out_vcc,new_skb);
193 return 0;
197 static int atmtcp_v_proc(struct atm_dev *dev,loff_t *pos,char *page)
199 struct atmtcp_dev_data *dev_data = PRIV(dev);
201 if (*pos) return 0;
202 if (!dev_data->persist) return sprintf(page,"ephemeral\n");
203 return sprintf(page,"persistent, %sconnected\n",
204 dev_data->vcc ? "" : "dis");
208 static void atmtcp_c_close(struct atm_vcc *vcc)
210 struct atm_dev *atmtcp_dev;
211 struct atmtcp_dev_data *dev_data;
212 struct atm_vcc *walk;
214 atmtcp_dev = (struct atm_dev *) vcc->dev_data;
215 dev_data = PRIV(atmtcp_dev);
216 dev_data->vcc = NULL;
217 if (dev_data->persist) return;
218 PRIV(atmtcp_dev) = NULL;
219 kfree(dev_data);
220 shutdown_atm_dev(atmtcp_dev);
221 vcc->dev_data = NULL;
222 for (walk = atmtcp_dev->vccs; walk; walk = walk->next)
223 wake_up(&walk->sleep);
227 static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb)
229 struct atm_dev *dev;
230 struct atmtcp_hdr *hdr;
231 struct atm_vcc *out_vcc;
232 struct sk_buff *new_skb;
233 int result = 0;
235 if (!skb->len) return 0;
236 dev = vcc->dev_data;
237 hdr = (struct atmtcp_hdr *) skb->data;
238 if (hdr->length == ATMTCP_HDR_MAGIC) {
239 result = atmtcp_recv_control(
240 (struct atmtcp_control *) skb->data);
241 goto done;
243 for (out_vcc = dev->vccs; out_vcc; out_vcc = out_vcc->next)
244 if (out_vcc->vpi == ntohs(hdr->vpi) &&
245 out_vcc->vci == ntohs(hdr->vci) &&
246 out_vcc->qos.rxtp.traffic_class != ATM_NONE)
247 break;
248 if (!out_vcc) {
249 vcc->stats->tx_err++;
250 goto done;
252 skb_pull(skb,sizeof(struct atmtcp_hdr));
253 new_skb = atm_alloc_charge(out_vcc,skb->len,GFP_KERNEL);
254 if (!new_skb) {
255 result = -ENOBUFS;
256 goto done;
258 new_skb->stamp = xtime;
259 memcpy(skb_put(new_skb,skb->len),skb->data,skb->len);
260 out_vcc->push(out_vcc,new_skb);
261 done:
262 if (vcc->pop) vcc->pop(vcc,skb);
263 else dev_kfree_skb(skb);
264 return result;
269 * Device operations for the virtual ATM devices created by ATMTCP.
273 static struct atmdev_ops atmtcp_v_dev_ops = {
274 atmtcp_v_dev_close,
275 atmtcp_v_open,
276 atmtcp_v_close,
277 atmtcp_v_ioctl,
278 NULL, /* no getsockopt */
279 NULL, /* no setsockopt */
280 atmtcp_v_send,
281 NULL, /* no direct writes */
282 NULL, /* no send_oam */
283 NULL, /* no phy_put */
284 NULL, /* no phy_get */
285 NULL, /* no feedback */
286 NULL, /* no change_qos */
287 NULL, /* no free_rx_skb */
288 atmtcp_v_proc /* proc_read */
293 * Device operations for the ATMTCP control device.
297 static struct atmdev_ops atmtcp_c_dev_ops = {
298 NULL, /* no dev_close */
299 NULL, /* no open */
300 atmtcp_c_close,
301 NULL, /* no ioctl */
302 NULL, /* no getsockopt */
303 NULL, /* no setsockopt */
304 atmtcp_c_send,
305 NULL, /* no sg_send */
306 NULL, /* no send_oam */
307 NULL, /* no phy_put */
308 NULL, /* no phy_get */
309 NULL, /* no feedback */
310 NULL, /* no change_qos */
311 NULL, /* no free_rx_skb */
312 NULL /* no proc_read */
316 static struct atm_dev atmtcp_control_dev = {
317 &atmtcp_c_dev_ops,
318 NULL, /* no PHY */
319 "atmtcp", /* type */
320 999, /* dummy device number */
321 NULL,NULL, /* pretend not to have any VCCs */
322 NULL,NULL, /* no data */
323 0, /* no flags */
324 NULL, /* no local address */
325 { 0 } /* no ESI, no statistics */
329 static int atmtcp_create(int itf,int persist,struct atm_dev **result)
331 struct atmtcp_dev_data *dev_data;
332 struct atm_dev *dev;
334 dev_data = kmalloc(sizeof(*dev_data),GFP_KERNEL);
335 if (!dev_data) return -ENOMEM;
336 dev = atm_dev_register(DEV_LABEL,&atmtcp_v_dev_ops,itf,0);
337 if (!dev) {
338 kfree(dev_data);
339 return itf == -1 ? -ENOMEM : -EBUSY;
341 MOD_INC_USE_COUNT;
342 dev->ci_range.vpi_bits = MAX_VPI_BITS;
343 dev->ci_range.vci_bits = MAX_VCI_BITS;
344 PRIV(dev) = dev_data;
345 PRIV(dev)->vcc = NULL;
346 PRIV(dev)->persist = persist;
347 if (result) *result = dev;
348 return 0;
352 int atmtcp_attach(struct atm_vcc *vcc,int itf)
354 struct atm_dev *dev;
356 dev = NULL;
357 if (itf != -1) dev = atm_find_dev(itf);
358 if (dev) {
359 if (dev->ops != &atmtcp_v_dev_ops) return -EMEDIUMTYPE;
360 if (PRIV(dev)->vcc) return -EBUSY;
362 else {
363 int error;
365 error = atmtcp_create(itf,0,&dev);
366 if (error) return error;
368 PRIV(dev)->vcc = vcc;
369 bind_vcc(vcc,&atmtcp_control_dev);
370 vcc->flags |= ATM_VF_READY | ATM_VF_META;
371 vcc->dev_data = dev;
372 (void) atm_init_aal5(vcc); /* @@@ losing AAL in transit ... */
373 vcc->stats = &atmtcp_control_dev.stats.aal5;
374 return dev->number;
378 int atmtcp_create_persistent(int itf)
380 return atmtcp_create(itf,1,NULL);
384 int atmtcp_remove_persistent(int itf)
386 struct atm_dev *dev;
387 struct atmtcp_dev_data *dev_data;
389 dev = atm_find_dev(itf);
390 if (!dev) return -ENODEV;
391 if (dev->ops != &atmtcp_v_dev_ops) return -EMEDIUMTYPE;
392 dev_data = PRIV(dev);
393 if (!dev_data->persist) return 0;
394 dev_data->persist = 0;
395 if (PRIV(dev)->vcc) return 0;
396 kfree(dev_data);
397 shutdown_atm_dev(dev);
398 return 0;
402 #ifdef MODULE
404 int init_module(void)
406 atm_tcp_ops.attach = atmtcp_attach;
407 atm_tcp_ops.create_persistent = atmtcp_create_persistent;
408 atm_tcp_ops.remove_persistent = atmtcp_remove_persistent;
409 return 0;
413 void cleanup_module(void)
415 atm_tcp_ops.attach = NULL;
416 atm_tcp_ops.create_persistent = NULL;
417 atm_tcp_ops.remove_persistent = NULL;
420 #else
422 struct atm_tcp_ops atm_tcp_ops = {
423 atmtcp_attach, /* attach */
424 atmtcp_create_persistent, /* create_persistent */
425 atmtcp_remove_persistent /* remove_persistent */
428 #endif