1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * NET3: Fibre Channel device handling subroutines 4 * 5 * Vineet Abraham <vma@iol.unh.edu> 6 * v 1.0 03/22/99 7 */ 8 9 #include <linux/uaccess.h> 10 #include <linux/types.h> 11 #include <linux/kernel.h> 12 #include <linux/string.h> 13 #include <linux/mm.h> 14 #include <linux/socket.h> 15 #include <linux/in.h> 16 #include <linux/inet.h> 17 #include <linux/netdevice.h> 18 #include <linux/fcdevice.h> 19 #include <linux/skbuff.h> 20 #include <linux/errno.h> 21 #include <linux/timer.h> 22 #include <linux/net.h> 23 #include <linux/proc_fs.h> 24 #include <linux/init.h> 25 #include <linux/export.h> 26 #include <net/arp.h> 27 28 /* 29 * Put the headers on a Fibre Channel packet. 30 */ 31 32 static int fc_header(struct sk_buff *skb, struct net_device *dev, 33 unsigned short type, 34 const void *daddr, const void *saddr, unsigned int len) 35 { 36 struct fch_hdr *fch; 37 int hdr_len; 38 39 /* 40 * Add the 802.2 SNAP header if IP as the IPv4 code calls 41 * dev->hard_header directly. 42 */ 43 if (type == ETH_P_IP || type == ETH_P_ARP) 44 { 45 struct fcllc *fcllc; 46 47 hdr_len = sizeof(struct fch_hdr) + sizeof(struct fcllc); 48 fch = skb_push(skb, hdr_len); 49 fcllc = (struct fcllc *)(fch+1); 50 fcllc->dsap = fcllc->ssap = EXTENDED_SAP; 51 fcllc->llc = UI_CMD; 52 fcllc->protid[0] = fcllc->protid[1] = fcllc->protid[2] = 0x00; 53 fcllc->ethertype = htons(type); 54 } 55 else 56 { 57 hdr_len = sizeof(struct fch_hdr); 58 fch = skb_push(skb, hdr_len); 59 } 60 61 if(saddr) 62 memcpy(fch->saddr,saddr,dev->addr_len); 63 else 64 memcpy(fch->saddr,dev->dev_addr,dev->addr_len); 65 66 if(daddr) 67 { 68 memcpy(fch->daddr,daddr,dev->addr_len); 69 return hdr_len; 70 } 71 return -hdr_len; 72 } 73 74 static const struct header_ops fc_header_ops = { 75 .create = fc_header, 76 }; 77 78 static void fc_setup(struct net_device *dev) 79 { 80 dev->header_ops = &fc_header_ops; 81 dev->type = ARPHRD_IEEE802; 82 dev->hard_header_len = FC_HLEN; 83 dev->mtu = 2024; 84 dev->addr_len = FC_ALEN; 85 dev->tx_queue_len = 100; /* Long queues on fc */ 86 dev->flags = IFF_BROADCAST; 87 88 memset(dev->broadcast, 0xFF, FC_ALEN); 89 } 90 91 /** 92 * alloc_fcdev - Register fibre channel device 93 * @sizeof_priv: Size of additional driver-private structure to be allocated 94 * for this fibre channel device 95 * 96 * Fill in the fields of the device structure with fibre channel-generic values. 97 * 98 * Constructs a new net device, complete with a private data area of 99 * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for 100 * this private data area. 101 */ 102 struct net_device *alloc_fcdev(int sizeof_priv) 103 { 104 return alloc_netdev(sizeof_priv, "fc%d", NET_NAME_UNKNOWN, fc_setup); 105 } 106 EXPORT_SYMBOL(alloc_fcdev); 107