1*2874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * NET3: Fibre Channel device handling subroutines
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Vineet Abraham <vma@iol.unh.edu>
61da177e4SLinus Torvalds * v 1.0 03/22/99
71da177e4SLinus Torvalds */
81da177e4SLinus Torvalds
97c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
101da177e4SLinus Torvalds #include <linux/types.h>
111da177e4SLinus Torvalds #include <linux/kernel.h>
121da177e4SLinus Torvalds #include <linux/string.h>
131da177e4SLinus Torvalds #include <linux/mm.h>
141da177e4SLinus Torvalds #include <linux/socket.h>
151da177e4SLinus Torvalds #include <linux/in.h>
161da177e4SLinus Torvalds #include <linux/inet.h>
171da177e4SLinus Torvalds #include <linux/netdevice.h>
181da177e4SLinus Torvalds #include <linux/fcdevice.h>
191da177e4SLinus Torvalds #include <linux/skbuff.h>
201da177e4SLinus Torvalds #include <linux/errno.h>
211da177e4SLinus Torvalds #include <linux/timer.h>
221da177e4SLinus Torvalds #include <linux/net.h>
231da177e4SLinus Torvalds #include <linux/proc_fs.h>
241da177e4SLinus Torvalds #include <linux/init.h>
25bc3b2d7fSPaul Gortmaker #include <linux/export.h>
261da177e4SLinus Torvalds #include <net/arp.h>
271da177e4SLinus Torvalds
281da177e4SLinus Torvalds /*
291da177e4SLinus Torvalds * Put the headers on a Fibre Channel packet.
301da177e4SLinus Torvalds */
311da177e4SLinus Torvalds
fc_header(struct sk_buff * skb,struct net_device * dev,unsigned short type,const void * daddr,const void * saddr,unsigned int len)321da177e4SLinus Torvalds static int fc_header(struct sk_buff *skb, struct net_device *dev,
331da177e4SLinus Torvalds unsigned short type,
3495c96174SEric Dumazet const void *daddr, const void *saddr, unsigned int len)
351da177e4SLinus Torvalds {
361da177e4SLinus Torvalds struct fch_hdr *fch;
371da177e4SLinus Torvalds int hdr_len;
381da177e4SLinus Torvalds
391da177e4SLinus Torvalds /*
401da177e4SLinus Torvalds * Add the 802.2 SNAP header if IP as the IPv4 code calls
411da177e4SLinus Torvalds * dev->hard_header directly.
421da177e4SLinus Torvalds */
431da177e4SLinus Torvalds if (type == ETH_P_IP || type == ETH_P_ARP)
441da177e4SLinus Torvalds {
451da177e4SLinus Torvalds struct fcllc *fcllc;
461da177e4SLinus Torvalds
471da177e4SLinus Torvalds hdr_len = sizeof(struct fch_hdr) + sizeof(struct fcllc);
48d58ff351SJohannes Berg fch = skb_push(skb, hdr_len);
491da177e4SLinus Torvalds fcllc = (struct fcllc *)(fch+1);
501da177e4SLinus Torvalds fcllc->dsap = fcllc->ssap = EXTENDED_SAP;
511da177e4SLinus Torvalds fcllc->llc = UI_CMD;
521da177e4SLinus Torvalds fcllc->protid[0] = fcllc->protid[1] = fcllc->protid[2] = 0x00;
531da177e4SLinus Torvalds fcllc->ethertype = htons(type);
541da177e4SLinus Torvalds }
551da177e4SLinus Torvalds else
561da177e4SLinus Torvalds {
571da177e4SLinus Torvalds hdr_len = sizeof(struct fch_hdr);
58d58ff351SJohannes Berg fch = skb_push(skb, hdr_len);
591da177e4SLinus Torvalds }
601da177e4SLinus Torvalds
611da177e4SLinus Torvalds if(saddr)
621da177e4SLinus Torvalds memcpy(fch->saddr,saddr,dev->addr_len);
631da177e4SLinus Torvalds else
641da177e4SLinus Torvalds memcpy(fch->saddr,dev->dev_addr,dev->addr_len);
651da177e4SLinus Torvalds
661da177e4SLinus Torvalds if(daddr)
671da177e4SLinus Torvalds {
681da177e4SLinus Torvalds memcpy(fch->daddr,daddr,dev->addr_len);
69a02cec21SEric Dumazet return hdr_len;
701da177e4SLinus Torvalds }
711da177e4SLinus Torvalds return -hdr_len;
721da177e4SLinus Torvalds }
731da177e4SLinus Torvalds
743b04dddeSStephen Hemminger static const struct header_ops fc_header_ops = {
753b04dddeSStephen Hemminger .create = fc_header,
763b04dddeSStephen Hemminger };
773b04dddeSStephen Hemminger
fc_setup(struct net_device * dev)781da177e4SLinus Torvalds static void fc_setup(struct net_device *dev)
791da177e4SLinus Torvalds {
803b04dddeSStephen Hemminger dev->header_ops = &fc_header_ops;
811da177e4SLinus Torvalds dev->type = ARPHRD_IEEE802;
821da177e4SLinus Torvalds dev->hard_header_len = FC_HLEN;
831da177e4SLinus Torvalds dev->mtu = 2024;
841da177e4SLinus Torvalds dev->addr_len = FC_ALEN;
851da177e4SLinus Torvalds dev->tx_queue_len = 100; /* Long queues on fc */
861da177e4SLinus Torvalds dev->flags = IFF_BROADCAST;
871da177e4SLinus Torvalds
881da177e4SLinus Torvalds memset(dev->broadcast, 0xFF, FC_ALEN);
891da177e4SLinus Torvalds }
901da177e4SLinus Torvalds
911da177e4SLinus Torvalds /**
921da177e4SLinus Torvalds * alloc_fcdev - Register fibre channel device
931da177e4SLinus Torvalds * @sizeof_priv: Size of additional driver-private structure to be allocated
941da177e4SLinus Torvalds * for this fibre channel device
951da177e4SLinus Torvalds *
961da177e4SLinus Torvalds * Fill in the fields of the device structure with fibre channel-generic values.
971da177e4SLinus Torvalds *
981da177e4SLinus Torvalds * Constructs a new net device, complete with a private data area of
991da177e4SLinus Torvalds * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for
1001da177e4SLinus Torvalds * this private data area.
1011da177e4SLinus Torvalds */
alloc_fcdev(int sizeof_priv)1021da177e4SLinus Torvalds struct net_device *alloc_fcdev(int sizeof_priv)
1031da177e4SLinus Torvalds {
104c835a677STom Gundersen return alloc_netdev(sizeof_priv, "fc%d", NET_NAME_UNKNOWN, fc_setup);
1051da177e4SLinus Torvalds }
1061da177e4SLinus Torvalds EXPORT_SYMBOL(alloc_fcdev);
107