0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #include <linux/interrupt.h>
0020 #include <linux/kernel.h>
0021 #include <linux/mutex.h>
0022 #include <linux/netdevice.h>
0023 #include <linux/ppp_channel.h>
0024 #include <linux/ppp_defs.h>
0025 #include <linux/slab.h>
0026 #include <linux/ppp-ioctl.h>
0027 #include <linux/skbuff.h>
0028
0029 #include "network.h"
0030 #include "hardware.h"
0031 #include "main.h"
0032 #include "tty.h"
0033
0034 #define MAX_ASSOCIATED_TTYS 2
0035
0036 #define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
0037
0038 struct ipw_network {
0039
0040 struct ipw_hardware *hardware;
0041
0042 struct ppp_channel *ppp_channel;
0043
0044 struct ipw_tty *associated_ttys[NO_OF_IPW_CHANNELS][MAX_ASSOCIATED_TTYS];
0045
0046 int ppp_blocked;
0047
0048 int outgoing_packets_queued;
0049
0050 spinlock_t lock;
0051 struct mutex close_lock;
0052
0053
0054 unsigned int flags;
0055 unsigned int rbits;
0056 u32 xaccm[8];
0057 u32 raccm;
0058 int mru;
0059
0060 int shutting_down;
0061 unsigned int ras_control_lines;
0062
0063 struct work_struct work_go_online;
0064 struct work_struct work_go_offline;
0065 };
0066
0067 static void notify_packet_sent(void *callback_data, unsigned int packet_length)
0068 {
0069 struct ipw_network *network = callback_data;
0070 unsigned long flags;
0071
0072 spin_lock_irqsave(&network->lock, flags);
0073 network->outgoing_packets_queued--;
0074 if (network->ppp_channel != NULL) {
0075 if (network->ppp_blocked) {
0076 network->ppp_blocked = 0;
0077 spin_unlock_irqrestore(&network->lock, flags);
0078 ppp_output_wakeup(network->ppp_channel);
0079 if (ipwireless_debug)
0080 printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
0081 ": ppp unblocked\n");
0082 } else
0083 spin_unlock_irqrestore(&network->lock, flags);
0084 } else
0085 spin_unlock_irqrestore(&network->lock, flags);
0086 }
0087
0088
0089
0090
0091 static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel,
0092 struct sk_buff *skb)
0093 {
0094 struct ipw_network *network = ppp_channel->private;
0095 unsigned long flags;
0096
0097 spin_lock_irqsave(&network->lock, flags);
0098 if (network->outgoing_packets_queued < ipwireless_out_queue) {
0099 unsigned char *buf;
0100 static unsigned char header[] = {
0101 PPP_ALLSTATIONS,
0102 PPP_UI,
0103 };
0104 int ret;
0105
0106 network->outgoing_packets_queued++;
0107 spin_unlock_irqrestore(&network->lock, flags);
0108
0109
0110
0111
0112
0113 if (skb_headroom(skb) >= 2) {
0114 memcpy(skb_push(skb, 2), header, 2);
0115 ret = ipwireless_send_packet(network->hardware,
0116 IPW_CHANNEL_RAS, skb->data,
0117 skb->len,
0118 notify_packet_sent,
0119 network);
0120 if (ret < 0) {
0121 skb_pull(skb, 2);
0122 return 0;
0123 }
0124 } else {
0125
0126 buf = kmalloc(skb->len + 2, GFP_ATOMIC);
0127 if (!buf)
0128 return 0;
0129 memcpy(buf + 2, skb->data, skb->len);
0130 memcpy(buf, header, 2);
0131 ret = ipwireless_send_packet(network->hardware,
0132 IPW_CHANNEL_RAS, buf,
0133 skb->len + 2,
0134 notify_packet_sent,
0135 network);
0136 kfree(buf);
0137 if (ret < 0)
0138 return 0;
0139 }
0140 kfree_skb(skb);
0141 return 1;
0142 } else {
0143
0144
0145
0146
0147 network->ppp_blocked = 1;
0148 spin_unlock_irqrestore(&network->lock, flags);
0149 if (ipwireless_debug)
0150 printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": ppp blocked\n");
0151 return 0;
0152 }
0153 }
0154
0155
0156 static int ipwireless_ppp_ioctl(struct ppp_channel *ppp_channel,
0157 unsigned int cmd, unsigned long arg)
0158 {
0159 struct ipw_network *network = ppp_channel->private;
0160 int err, val;
0161 u32 accm[8];
0162 int __user *user_arg = (int __user *) arg;
0163
0164 err = -EFAULT;
0165 switch (cmd) {
0166 case PPPIOCGFLAGS:
0167 val = network->flags | network->rbits;
0168 if (put_user(val, user_arg))
0169 break;
0170 err = 0;
0171 break;
0172
0173 case PPPIOCSFLAGS:
0174 if (get_user(val, user_arg))
0175 break;
0176 network->flags = val & ~SC_RCV_BITS;
0177 network->rbits = val & SC_RCV_BITS;
0178 err = 0;
0179 break;
0180
0181 case PPPIOCGASYNCMAP:
0182 if (put_user(network->xaccm[0], user_arg))
0183 break;
0184 err = 0;
0185 break;
0186
0187 case PPPIOCSASYNCMAP:
0188 if (get_user(network->xaccm[0], user_arg))
0189 break;
0190 err = 0;
0191 break;
0192
0193 case PPPIOCGRASYNCMAP:
0194 if (put_user(network->raccm, user_arg))
0195 break;
0196 err = 0;
0197 break;
0198
0199 case PPPIOCSRASYNCMAP:
0200 if (get_user(network->raccm, user_arg))
0201 break;
0202 err = 0;
0203 break;
0204
0205 case PPPIOCGXASYNCMAP:
0206 if (copy_to_user((void __user *) arg, network->xaccm,
0207 sizeof(network->xaccm)))
0208 break;
0209 err = 0;
0210 break;
0211
0212 case PPPIOCSXASYNCMAP:
0213 if (copy_from_user(accm, (void __user *) arg, sizeof(accm)))
0214 break;
0215 accm[2] &= ~0x40000000U;
0216 accm[3] |= 0x60000000U;
0217 memcpy(network->xaccm, accm, sizeof(network->xaccm));
0218 err = 0;
0219 break;
0220
0221 case PPPIOCGMRU:
0222 if (put_user(network->mru, user_arg))
0223 break;
0224 err = 0;
0225 break;
0226
0227 case PPPIOCSMRU:
0228 if (get_user(val, user_arg))
0229 break;
0230 if (val < PPP_MRU)
0231 val = PPP_MRU;
0232 network->mru = val;
0233 err = 0;
0234 break;
0235
0236 default:
0237 err = -ENOTTY;
0238 }
0239
0240 return err;
0241 }
0242
0243 static const struct ppp_channel_ops ipwireless_ppp_channel_ops = {
0244 .start_xmit = ipwireless_ppp_start_xmit,
0245 .ioctl = ipwireless_ppp_ioctl
0246 };
0247
0248 static void do_go_online(struct work_struct *work_go_online)
0249 {
0250 struct ipw_network *network =
0251 container_of(work_go_online, struct ipw_network,
0252 work_go_online);
0253 unsigned long flags;
0254
0255 spin_lock_irqsave(&network->lock, flags);
0256 if (!network->ppp_channel) {
0257 struct ppp_channel *channel;
0258
0259 spin_unlock_irqrestore(&network->lock, flags);
0260 channel = kzalloc(sizeof(struct ppp_channel), GFP_KERNEL);
0261 if (!channel) {
0262 printk(KERN_ERR IPWIRELESS_PCCARD_NAME
0263 ": unable to allocate PPP channel\n");
0264 return;
0265 }
0266 channel->private = network;
0267 channel->mtu = 16384;
0268 channel->hdrlen = 2;
0269 channel->ops = &ipwireless_ppp_channel_ops;
0270
0271 network->flags = 0;
0272 network->rbits = 0;
0273 network->mru = PPP_MRU;
0274 memset(network->xaccm, 0, sizeof(network->xaccm));
0275 network->xaccm[0] = ~0U;
0276 network->xaccm[3] = 0x60000000U;
0277 network->raccm = ~0U;
0278 if (ppp_register_channel(channel) < 0) {
0279 printk(KERN_ERR IPWIRELESS_PCCARD_NAME
0280 ": unable to register PPP channel\n");
0281 kfree(channel);
0282 return;
0283 }
0284 spin_lock_irqsave(&network->lock, flags);
0285 network->ppp_channel = channel;
0286 }
0287 spin_unlock_irqrestore(&network->lock, flags);
0288 }
0289
0290 static void do_go_offline(struct work_struct *work_go_offline)
0291 {
0292 struct ipw_network *network =
0293 container_of(work_go_offline, struct ipw_network,
0294 work_go_offline);
0295 unsigned long flags;
0296
0297 mutex_lock(&network->close_lock);
0298 spin_lock_irqsave(&network->lock, flags);
0299 if (network->ppp_channel != NULL) {
0300 struct ppp_channel *channel = network->ppp_channel;
0301
0302 network->ppp_channel = NULL;
0303 spin_unlock_irqrestore(&network->lock, flags);
0304 mutex_unlock(&network->close_lock);
0305 ppp_unregister_channel(channel);
0306 } else {
0307 spin_unlock_irqrestore(&network->lock, flags);
0308 mutex_unlock(&network->close_lock);
0309 }
0310 }
0311
0312 void ipwireless_network_notify_control_line_change(struct ipw_network *network,
0313 unsigned int channel_idx,
0314 unsigned int control_lines,
0315 unsigned int changed_mask)
0316 {
0317 int i;
0318
0319 if (channel_idx == IPW_CHANNEL_RAS)
0320 network->ras_control_lines = control_lines;
0321
0322 for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) {
0323 struct ipw_tty *tty =
0324 network->associated_ttys[channel_idx][i];
0325
0326
0327
0328
0329
0330
0331
0332 if (tty)
0333 ipwireless_tty_notify_control_line_change(tty,
0334 channel_idx,
0335 control_lines,
0336 changed_mask);
0337 }
0338 }
0339
0340
0341
0342
0343
0344
0345 static struct sk_buff *ipw_packet_received_skb(unsigned char *data,
0346 unsigned int length)
0347 {
0348 struct sk_buff *skb;
0349
0350 if (length > 2 && data[0] == PPP_ALLSTATIONS && data[1] == PPP_UI) {
0351 length -= 2;
0352 data += 2;
0353 }
0354
0355 skb = dev_alloc_skb(length + 4);
0356 if (skb == NULL)
0357 return NULL;
0358 skb_reserve(skb, 2);
0359 skb_put_data(skb, data, length);
0360
0361 return skb;
0362 }
0363
0364 void ipwireless_network_packet_received(struct ipw_network *network,
0365 unsigned int channel_idx,
0366 unsigned char *data,
0367 unsigned int length)
0368 {
0369 int i;
0370 unsigned long flags;
0371
0372 for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) {
0373 struct ipw_tty *tty = network->associated_ttys[channel_idx][i];
0374
0375 if (!tty)
0376 continue;
0377
0378
0379
0380
0381
0382
0383
0384 if (channel_idx == IPW_CHANNEL_RAS
0385 && (network->ras_control_lines &
0386 IPW_CONTROL_LINE_DCD) != 0
0387 && ipwireless_tty_is_modem(tty)) {
0388
0389
0390
0391
0392
0393 mutex_lock(&network->close_lock);
0394 spin_lock_irqsave(&network->lock, flags);
0395 if (network->ppp_channel != NULL) {
0396 struct sk_buff *skb;
0397
0398 spin_unlock_irqrestore(&network->lock,
0399 flags);
0400
0401
0402 skb = ipw_packet_received_skb(data, length);
0403 if (skb)
0404 ppp_input(network->ppp_channel, skb);
0405 } else
0406 spin_unlock_irqrestore(&network->lock,
0407 flags);
0408 mutex_unlock(&network->close_lock);
0409 }
0410
0411 else
0412 ipwireless_tty_received(tty, data, length);
0413 }
0414 }
0415
0416 struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw)
0417 {
0418 struct ipw_network *network =
0419 kzalloc(sizeof(struct ipw_network), GFP_KERNEL);
0420
0421 if (!network)
0422 return NULL;
0423
0424 spin_lock_init(&network->lock);
0425 mutex_init(&network->close_lock);
0426
0427 network->hardware = hw;
0428
0429 INIT_WORK(&network->work_go_online, do_go_online);
0430 INIT_WORK(&network->work_go_offline, do_go_offline);
0431
0432 ipwireless_associate_network(hw, network);
0433
0434 return network;
0435 }
0436
0437 void ipwireless_network_free(struct ipw_network *network)
0438 {
0439 network->shutting_down = 1;
0440
0441 ipwireless_ppp_close(network);
0442 flush_work(&network->work_go_online);
0443 flush_work(&network->work_go_offline);
0444
0445 ipwireless_stop_interrupts(network->hardware);
0446 ipwireless_associate_network(network->hardware, NULL);
0447
0448 kfree(network);
0449 }
0450
0451 void ipwireless_associate_network_tty(struct ipw_network *network,
0452 unsigned int channel_idx,
0453 struct ipw_tty *tty)
0454 {
0455 int i;
0456
0457 for (i = 0; i < MAX_ASSOCIATED_TTYS; i++)
0458 if (network->associated_ttys[channel_idx][i] == NULL) {
0459 network->associated_ttys[channel_idx][i] = tty;
0460 break;
0461 }
0462 }
0463
0464 void ipwireless_disassociate_network_ttys(struct ipw_network *network,
0465 unsigned int channel_idx)
0466 {
0467 int i;
0468
0469 for (i = 0; i < MAX_ASSOCIATED_TTYS; i++)
0470 network->associated_ttys[channel_idx][i] = NULL;
0471 }
0472
0473 void ipwireless_ppp_open(struct ipw_network *network)
0474 {
0475 if (ipwireless_debug)
0476 printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": online\n");
0477 schedule_work(&network->work_go_online);
0478 }
0479
0480 void ipwireless_ppp_close(struct ipw_network *network)
0481 {
0482
0483 if (ipwireless_debug)
0484 printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": offline\n");
0485 schedule_work(&network->work_go_offline);
0486 }
0487
0488 int ipwireless_ppp_channel_index(struct ipw_network *network)
0489 {
0490 int ret = -1;
0491 unsigned long flags;
0492
0493 spin_lock_irqsave(&network->lock, flags);
0494 if (network->ppp_channel != NULL)
0495 ret = ppp_channel_index(network->ppp_channel);
0496 spin_unlock_irqrestore(&network->lock, flags);
0497
0498 return ret;
0499 }
0500
0501 int ipwireless_ppp_unit_number(struct ipw_network *network)
0502 {
0503 int ret = -1;
0504 unsigned long flags;
0505
0506 spin_lock_irqsave(&network->lock, flags);
0507 if (network->ppp_channel != NULL)
0508 ret = ppp_unit_number(network->ppp_channel);
0509 spin_unlock_irqrestore(&network->lock, flags);
0510
0511 return ret;
0512 }
0513
0514 int ipwireless_ppp_mru(const struct ipw_network *network)
0515 {
0516 return network->mru;
0517 }