162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * NET3: Fibre Channel device handling subroutines 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Vineet Abraham <vma@iol.unh.edu> 662306a36Sopenharmony_ci * v 1.0 03/22/99 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/uaccess.h> 1062306a36Sopenharmony_ci#include <linux/types.h> 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci#include <linux/string.h> 1362306a36Sopenharmony_ci#include <linux/mm.h> 1462306a36Sopenharmony_ci#include <linux/socket.h> 1562306a36Sopenharmony_ci#include <linux/in.h> 1662306a36Sopenharmony_ci#include <linux/inet.h> 1762306a36Sopenharmony_ci#include <linux/netdevice.h> 1862306a36Sopenharmony_ci#include <linux/fcdevice.h> 1962306a36Sopenharmony_ci#include <linux/skbuff.h> 2062306a36Sopenharmony_ci#include <linux/errno.h> 2162306a36Sopenharmony_ci#include <linux/timer.h> 2262306a36Sopenharmony_ci#include <linux/net.h> 2362306a36Sopenharmony_ci#include <linux/proc_fs.h> 2462306a36Sopenharmony_ci#include <linux/init.h> 2562306a36Sopenharmony_ci#include <linux/export.h> 2662306a36Sopenharmony_ci#include <net/arp.h> 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci/* 2962306a36Sopenharmony_ci * Put the headers on a Fibre Channel packet. 3062306a36Sopenharmony_ci */ 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic int fc_header(struct sk_buff *skb, struct net_device *dev, 3362306a36Sopenharmony_ci unsigned short type, 3462306a36Sopenharmony_ci const void *daddr, const void *saddr, unsigned int len) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci struct fch_hdr *fch; 3762306a36Sopenharmony_ci int hdr_len; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci /* 4062306a36Sopenharmony_ci * Add the 802.2 SNAP header if IP as the IPv4 code calls 4162306a36Sopenharmony_ci * dev->hard_header directly. 4262306a36Sopenharmony_ci */ 4362306a36Sopenharmony_ci if (type == ETH_P_IP || type == ETH_P_ARP) 4462306a36Sopenharmony_ci { 4562306a36Sopenharmony_ci struct fcllc *fcllc; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci hdr_len = sizeof(struct fch_hdr) + sizeof(struct fcllc); 4862306a36Sopenharmony_ci fch = skb_push(skb, hdr_len); 4962306a36Sopenharmony_ci fcllc = (struct fcllc *)(fch+1); 5062306a36Sopenharmony_ci fcllc->dsap = fcllc->ssap = EXTENDED_SAP; 5162306a36Sopenharmony_ci fcllc->llc = UI_CMD; 5262306a36Sopenharmony_ci fcllc->protid[0] = fcllc->protid[1] = fcllc->protid[2] = 0x00; 5362306a36Sopenharmony_ci fcllc->ethertype = htons(type); 5462306a36Sopenharmony_ci } 5562306a36Sopenharmony_ci else 5662306a36Sopenharmony_ci { 5762306a36Sopenharmony_ci hdr_len = sizeof(struct fch_hdr); 5862306a36Sopenharmony_ci fch = skb_push(skb, hdr_len); 5962306a36Sopenharmony_ci } 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci if(saddr) 6262306a36Sopenharmony_ci memcpy(fch->saddr,saddr,dev->addr_len); 6362306a36Sopenharmony_ci else 6462306a36Sopenharmony_ci memcpy(fch->saddr,dev->dev_addr,dev->addr_len); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci if(daddr) 6762306a36Sopenharmony_ci { 6862306a36Sopenharmony_ci memcpy(fch->daddr,daddr,dev->addr_len); 6962306a36Sopenharmony_ci return hdr_len; 7062306a36Sopenharmony_ci } 7162306a36Sopenharmony_ci return -hdr_len; 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic const struct header_ops fc_header_ops = { 7562306a36Sopenharmony_ci .create = fc_header, 7662306a36Sopenharmony_ci}; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cistatic void fc_setup(struct net_device *dev) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci dev->header_ops = &fc_header_ops; 8162306a36Sopenharmony_ci dev->type = ARPHRD_IEEE802; 8262306a36Sopenharmony_ci dev->hard_header_len = FC_HLEN; 8362306a36Sopenharmony_ci dev->mtu = 2024; 8462306a36Sopenharmony_ci dev->addr_len = FC_ALEN; 8562306a36Sopenharmony_ci dev->tx_queue_len = 100; /* Long queues on fc */ 8662306a36Sopenharmony_ci dev->flags = IFF_BROADCAST; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci memset(dev->broadcast, 0xFF, FC_ALEN); 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci/** 9262306a36Sopenharmony_ci * alloc_fcdev - Register fibre channel device 9362306a36Sopenharmony_ci * @sizeof_priv: Size of additional driver-private structure to be allocated 9462306a36Sopenharmony_ci * for this fibre channel device 9562306a36Sopenharmony_ci * 9662306a36Sopenharmony_ci * Fill in the fields of the device structure with fibre channel-generic values. 9762306a36Sopenharmony_ci * 9862306a36Sopenharmony_ci * Constructs a new net device, complete with a private data area of 9962306a36Sopenharmony_ci * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for 10062306a36Sopenharmony_ci * this private data area. 10162306a36Sopenharmony_ci */ 10262306a36Sopenharmony_cistruct net_device *alloc_fcdev(int sizeof_priv) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci return alloc_netdev(sizeof_priv, "fc%d", NET_NAME_UNKNOWN, fc_setup); 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ciEXPORT_SYMBOL(alloc_fcdev); 107