diff options
Diffstat (limited to 'net/802/fc.c')
-rw-r--r-- | net/802/fc.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/net/802/fc.c b/net/802/fc.c new file mode 100644 index 000000000000..640d34e026c2 --- /dev/null +++ b/net/802/fc.c | |||
@@ -0,0 +1,130 @@ | |||
1 | /* | ||
2 | * NET3: Fibre Channel device handling subroutines | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * Vineet Abraham <vma@iol.unh.edu> | ||
10 | * v 1.0 03/22/99 | ||
11 | */ | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #include <asm/uaccess.h> | ||
15 | #include <asm/system.h> | ||
16 | #include <linux/types.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/string.h> | ||
20 | #include <linux/mm.h> | ||
21 | #include <linux/socket.h> | ||
22 | #include <linux/in.h> | ||
23 | #include <linux/inet.h> | ||
24 | #include <linux/netdevice.h> | ||
25 | #include <linux/fcdevice.h> | ||
26 | #include <linux/skbuff.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/timer.h> | ||
29 | #include <linux/net.h> | ||
30 | #include <linux/proc_fs.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <net/arp.h> | ||
33 | |||
34 | /* | ||
35 | * Put the headers on a Fibre Channel packet. | ||
36 | */ | ||
37 | |||
38 | static int fc_header(struct sk_buff *skb, struct net_device *dev, | ||
39 | unsigned short type, | ||
40 | void *daddr, void *saddr, unsigned len) | ||
41 | { | ||
42 | struct fch_hdr *fch; | ||
43 | int hdr_len; | ||
44 | |||
45 | /* | ||
46 | * Add the 802.2 SNAP header if IP as the IPv4 code calls | ||
47 | * dev->hard_header directly. | ||
48 | */ | ||
49 | if (type == ETH_P_IP || type == ETH_P_ARP) | ||
50 | { | ||
51 | struct fcllc *fcllc; | ||
52 | |||
53 | hdr_len = sizeof(struct fch_hdr) + sizeof(struct fcllc); | ||
54 | fch = (struct fch_hdr *)skb_push(skb, hdr_len); | ||
55 | fcllc = (struct fcllc *)(fch+1); | ||
56 | fcllc->dsap = fcllc->ssap = EXTENDED_SAP; | ||
57 | fcllc->llc = UI_CMD; | ||
58 | fcllc->protid[0] = fcllc->protid[1] = fcllc->protid[2] = 0x00; | ||
59 | fcllc->ethertype = htons(type); | ||
60 | } | ||
61 | else | ||
62 | { | ||
63 | hdr_len = sizeof(struct fch_hdr); | ||
64 | fch = (struct fch_hdr *)skb_push(skb, hdr_len); | ||
65 | } | ||
66 | |||
67 | if(saddr) | ||
68 | memcpy(fch->saddr,saddr,dev->addr_len); | ||
69 | else | ||
70 | memcpy(fch->saddr,dev->dev_addr,dev->addr_len); | ||
71 | |||
72 | if(daddr) | ||
73 | { | ||
74 | memcpy(fch->daddr,daddr,dev->addr_len); | ||
75 | return(hdr_len); | ||
76 | } | ||
77 | return -hdr_len; | ||
78 | } | ||
79 | |||
80 | /* | ||
81 | * A neighbour discovery of some species (eg arp) has completed. We | ||
82 | * can now send the packet. | ||
83 | */ | ||
84 | |||
85 | static int fc_rebuild_header(struct sk_buff *skb) | ||
86 | { | ||
87 | struct fch_hdr *fch=(struct fch_hdr *)skb->data; | ||
88 | struct fcllc *fcllc=(struct fcllc *)(skb->data+sizeof(struct fch_hdr)); | ||
89 | if(fcllc->ethertype != htons(ETH_P_IP)) { | ||
90 | printk("fc_rebuild_header: Don't know how to resolve type %04X addresses ?\n",(unsigned int)htons(fcllc->ethertype)); | ||
91 | return 0; | ||
92 | } | ||
93 | #ifdef CONFIG_INET | ||
94 | return arp_find(fch->daddr, skb); | ||
95 | #else | ||
96 | return 0; | ||
97 | #endif | ||
98 | } | ||
99 | |||
100 | static void fc_setup(struct net_device *dev) | ||
101 | { | ||
102 | dev->hard_header = fc_header; | ||
103 | dev->rebuild_header = fc_rebuild_header; | ||
104 | |||
105 | dev->type = ARPHRD_IEEE802; | ||
106 | dev->hard_header_len = FC_HLEN; | ||
107 | dev->mtu = 2024; | ||
108 | dev->addr_len = FC_ALEN; | ||
109 | dev->tx_queue_len = 100; /* Long queues on fc */ | ||
110 | dev->flags = IFF_BROADCAST; | ||
111 | |||
112 | memset(dev->broadcast, 0xFF, FC_ALEN); | ||
113 | } | ||
114 | |||
115 | /** | ||
116 | * alloc_fcdev - Register fibre channel device | ||
117 | * @sizeof_priv: Size of additional driver-private structure to be allocated | ||
118 | * for this fibre channel device | ||
119 | * | ||
120 | * Fill in the fields of the device structure with fibre channel-generic values. | ||
121 | * | ||
122 | * Constructs a new net device, complete with a private data area of | ||
123 | * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for | ||
124 | * this private data area. | ||
125 | */ | ||
126 | struct net_device *alloc_fcdev(int sizeof_priv) | ||
127 | { | ||
128 | return alloc_netdev(sizeof_priv, "fc%d", fc_setup); | ||
129 | } | ||
130 | EXPORT_SYMBOL(alloc_fcdev); | ||