]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * NET3: Fibre Channel device handling subroutines | |
9afa0949 | 3 | * |
1da177e4 LT |
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 <[email protected]> | |
10 | * v 1.0 03/22/99 | |
11 | */ | |
12 | ||
1da177e4 LT |
13 | #include <asm/uaccess.h> |
14 | #include <asm/system.h> | |
15 | #include <linux/types.h> | |
16 | #include <linux/kernel.h> | |
1da177e4 LT |
17 | #include <linux/string.h> |
18 | #include <linux/mm.h> | |
19 | #include <linux/socket.h> | |
20 | #include <linux/in.h> | |
21 | #include <linux/inet.h> | |
22 | #include <linux/netdevice.h> | |
23 | #include <linux/fcdevice.h> | |
24 | #include <linux/skbuff.h> | |
25 | #include <linux/errno.h> | |
26 | #include <linux/timer.h> | |
27 | #include <linux/net.h> | |
28 | #include <linux/proc_fs.h> | |
29 | #include <linux/init.h> | |
30 | #include <net/arp.h> | |
31 | ||
32 | /* | |
9afa0949 | 33 | * Put the headers on a Fibre Channel packet. |
1da177e4 | 34 | */ |
9afa0949 | 35 | |
1da177e4 LT |
36 | static int fc_header(struct sk_buff *skb, struct net_device *dev, |
37 | unsigned short type, | |
3b04ddde | 38 | const void *daddr, const void *saddr, unsigned len) |
1da177e4 LT |
39 | { |
40 | struct fch_hdr *fch; | |
41 | int hdr_len; | |
42 | ||
9afa0949 YH |
43 | /* |
44 | * Add the 802.2 SNAP header if IP as the IPv4 code calls | |
1da177e4 LT |
45 | * dev->hard_header directly. |
46 | */ | |
47 | if (type == ETH_P_IP || type == ETH_P_ARP) | |
48 | { | |
49 | struct fcllc *fcllc; | |
50 | ||
51 | hdr_len = sizeof(struct fch_hdr) + sizeof(struct fcllc); | |
52 | fch = (struct fch_hdr *)skb_push(skb, hdr_len); | |
53 | fcllc = (struct fcllc *)(fch+1); | |
54 | fcllc->dsap = fcllc->ssap = EXTENDED_SAP; | |
55 | fcllc->llc = UI_CMD; | |
56 | fcllc->protid[0] = fcllc->protid[1] = fcllc->protid[2] = 0x00; | |
57 | fcllc->ethertype = htons(type); | |
58 | } | |
59 | else | |
60 | { | |
61 | hdr_len = sizeof(struct fch_hdr); | |
9afa0949 | 62 | fch = (struct fch_hdr *)skb_push(skb, hdr_len); |
1da177e4 LT |
63 | } |
64 | ||
65 | if(saddr) | |
66 | memcpy(fch->saddr,saddr,dev->addr_len); | |
67 | else | |
68 | memcpy(fch->saddr,dev->dev_addr,dev->addr_len); | |
69 | ||
9afa0949 | 70 | if(daddr) |
1da177e4 LT |
71 | { |
72 | memcpy(fch->daddr,daddr,dev->addr_len); | |
a02cec21 | 73 | return hdr_len; |
1da177e4 LT |
74 | } |
75 | return -hdr_len; | |
76 | } | |
9afa0949 | 77 | |
1da177e4 LT |
78 | /* |
79 | * A neighbour discovery of some species (eg arp) has completed. We | |
80 | * can now send the packet. | |
81 | */ | |
9afa0949 YH |
82 | |
83 | static int fc_rebuild_header(struct sk_buff *skb) | |
1da177e4 | 84 | { |
deb28d9b | 85 | #ifdef CONFIG_INET |
1da177e4 LT |
86 | struct fch_hdr *fch=(struct fch_hdr *)skb->data; |
87 | struct fcllc *fcllc=(struct fcllc *)(skb->data+sizeof(struct fch_hdr)); | |
88 | if(fcllc->ethertype != htons(ETH_P_IP)) { | |
57bf1451 | 89 | printk("fc_rebuild_header: Don't know how to resolve type %04X addresses ?\n", ntohs(fcllc->ethertype)); |
1da177e4 LT |
90 | return 0; |
91 | } | |
1da177e4 LT |
92 | return arp_find(fch->daddr, skb); |
93 | #else | |
94 | return 0; | |
95 | #endif | |
96 | } | |
97 | ||
3b04ddde SH |
98 | static const struct header_ops fc_header_ops = { |
99 | .create = fc_header, | |
100 | .rebuild = fc_rebuild_header, | |
101 | }; | |
102 | ||
1da177e4 LT |
103 | static void fc_setup(struct net_device *dev) |
104 | { | |
3b04ddde | 105 | dev->header_ops = &fc_header_ops; |
1da177e4 LT |
106 | dev->type = ARPHRD_IEEE802; |
107 | dev->hard_header_len = FC_HLEN; | |
108 | dev->mtu = 2024; | |
109 | dev->addr_len = FC_ALEN; | |
110 | dev->tx_queue_len = 100; /* Long queues on fc */ | |
111 | dev->flags = IFF_BROADCAST; | |
112 | ||
113 | memset(dev->broadcast, 0xFF, FC_ALEN); | |
114 | } | |
115 | ||
116 | /** | |
117 | * alloc_fcdev - Register fibre channel device | |
118 | * @sizeof_priv: Size of additional driver-private structure to be allocated | |
119 | * for this fibre channel device | |
120 | * | |
121 | * Fill in the fields of the device structure with fibre channel-generic values. | |
122 | * | |
123 | * Constructs a new net device, complete with a private data area of | |
124 | * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for | |
125 | * this private data area. | |
126 | */ | |
127 | struct net_device *alloc_fcdev(int sizeof_priv) | |
128 | { | |
129 | return alloc_netdev(sizeof_priv, "fc%d", fc_setup); | |
130 | } | |
131 | EXPORT_SYMBOL(alloc_fcdev); |