blob: 0d9232c63c52fb0c2eadffac0bb834c809aa58cb [file] [log] [blame]
/* Copyright (c) 2015 Google Inc.
* Copyright (C) 1991-2017, the Linux Kernel authors
*
* Dumping ground for converting between Akaros and Linux. */
#pragma once
#define ROS_KERN_LINUX_COMPAT_H
/* Common headers that most driver files will need */
#include <ros/common.h>
#include <assert.h>
#include <error.h>
#include <net/ip.h>
#include <kmalloc.h>
#include <kref.h>
#include <pmap.h>
#include <slab.h>
#include <smp.h>
#include <stdio.h>
#include <string.h>
#include <bitmap.h>
#include <umem.h>
#include <mmio.h>
#include <taskqueue.h>
#include <zlib.h>
#include <list.h>
#include <refd_pages.h>
#include <linux/errno.h>
/* temporary dumping ground */
#include "compat_todo.h"
//#define CONFIG_DCB
//#define CONFIG_NET_RX_BUSY_POLL 1
//#define CONFIG_NET_POLL_CONTROLLER 1
//#define CONFIG_INET 1 // will deal with this manually
#define CONFIG_PCI_MSI 1
static inline void synchronize_sched(void)
{
synchronize_rcu();
}
#define atomic_cmpxchg(_addr, _old, _new) \
({ \
typeof(_old) _ret; \
if (atomic_cas((_addr), (_old), (_new))) \
_ret = _old; \
else \
_ret = atomic_read(_addr); \
_ret; \
})
#define UINT_MAX UINT64_MAX
#define L1_CACHE_SHIFT (LOG2_UP(ARCH_CL_SIZE))
#define __stringify(x...) STRINGIFY(x)
/* Wanted to keep the _t variants in the code, in case that's useful in the
* future */
#define MIN_T(t, a, b) MIN(a, b)
#define MAX_T(t, a, b) MAX(a, b)
#define CLAMP(val, lo, hi) MIN((typeof(val))MAX(val, lo), hi)
#define CLAMP_T(t, val, lo, hi) CLAMP(val, lo, hi)
typedef physaddr_t dma_addr_t;
typedef int gfp_t;
/* these dma funcs are empty in linux with !CONFIG_NEED_DMA_MAP_STATE */
#define DEFINE_DMA_UNMAP_ADDR(ADDR_NAME)
#define DEFINE_DMA_UNMAP_LEN(LEN_NAME)
#define dma_unmap_addr(PTR, ADDR_NAME) (0)
#define dma_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0)
#define dma_unmap_len(PTR, LEN_NAME) (0)
#define dma_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL << (n)) - 1))
#define DMA_MASK_NONE 0x0ULL
enum dma_data_direction {
DMA_BIDIRECTIONAL = 0,
DMA_TO_DEVICE = 1,
DMA_FROM_DEVICE = 2,
DMA_NONE = 3,
};
static inline void *__dma_alloc_coherent(size_t size, dma_addr_t *dma_handle,
gfp_t flags)
{
void *vaddr = get_cont_pages(LOG2_UP(nr_pages(size)), flags);
if (!vaddr) {
*dma_handle = 0;
return 0;
}
*dma_handle = PADDR(vaddr);
return vaddr;
}
static inline void *__dma_zalloc_coherent(size_t size, dma_addr_t *dma_handle,
gfp_t flags)
{
void *vaddr = __dma_alloc_coherent(size, dma_handle, flags);
if (vaddr)
memset(vaddr, 0, size);
return vaddr;
}
static inline void __dma_free_coherent(size_t size, void *cpu_addr,
dma_addr_t dma_handle)
{
free_cont_pages(cpu_addr, LOG2_UP(nr_pages(size)));
}
static inline dma_addr_t __dma_map_single(void *cpu_addr, size_t size,
int direction)
{
return PADDR(cpu_addr);
}
static inline dma_addr_t __dma_map_page(struct page *page,
unsigned long offset, size_t size,
int direction)
{
assert(offset == 0);
return page2pa(page);
}
static inline int __dma_mapping_error(dma_addr_t dma_addr)
{
return (dma_addr == 0);
}
#define dma_unmap_single(...)
#define dma_unmap_page(...)
#define dma_set_mask_and_coherent(...) (0)
#define dma_sync_single_for_cpu(...)
#define dma_sync_single_for_device(...)
/* Wrappers to avoid struct device. Might want that one of these days.
*
* Note dma_alloc_coherent() does a zalloc. Some Linux drivers (r8169)
* accidentally assume the memory is zeroed, which may be what Linux allocators
* often do. */
#define dma_alloc_coherent(dev, size, dma_handlep, flag) \
__dma_zalloc_coherent(size, dma_handlep, flag)
#define dma_zalloc_coherent(dev, size, dma_handlep, flag) \
__dma_zalloc_coherent(size, dma_handlep, flag)
#define dma_free_coherent(dev, size, dma_handle, flag) \
__dma_free_coherent(size, dma_handle, flag)
#define dma_map_single(dev, addr, size, direction) \
__dma_map_single(addr, size, direction)
#define dma_map_page(dev, page, offset, size, direction) \
__dma_map_page(page, offset, size, direction)
#define dma_mapping_error(dev, handle) \
__dma_mapping_error(handle)
static void *vmalloc(size_t size)
{
void *vaddr = get_cont_pages(LOG2_UP(nr_pages(size)), MEM_WAIT);
/* zalloc, to be safe */
if (vaddr)
memset(vaddr, 0, size);
return vaddr;
}
/* Akaros needs to know the size, for now. So it's not quite compatible */
static void vfree(void *vaddr, size_t size)
{
free_cont_pages(vaddr, LOG2_UP(nr_pages(size)));
}
typedef int pci_power_t;
typedef int pm_message_t;
#define DEFINE_SEMAPHORE(name) \
struct semaphore name = SEMAPHORE_INITIALIZER_IRQSAVE(name, 1)
#define sema_init(sem, val) sem_init_irqsave(sem, val)
#define up(sem) sem_up(sem)
#define down(sem) sem_down(sem)
#define down_trylock(sem) ({!sem_trydown(sem);})
/* In lieu of spatching, I wanted to keep the distinction between down and
* down_interruptible/down_timeout. Akaros doesn't have the latter. */
#define down_interruptible(sem) ({sem_down(sem); 0;})
#define down_timeout(sem, timeout) ({sem_down(sem); 0;})
static void msleep(unsigned int msecs)
{
kthread_usleep(msecs * 1000);
}
#define mdelay(x) udelay((x) * 1000)
#define local_bh_disable() cmb()
#define local_bh_enable() cmb()
/* Linux printk front ends */
#ifndef pr_fmt
#define pr_fmt(fmt) fmt
#endif
#define KERN_EMERG ""
#define KERN_ALERT ""
#define KERN_CRIT ""
#define KERN_ERR ""
#define KERN_WARNING ""
#define KERN_NOTICE ""
#define KERN_INFO ""
#define KERN_CONT ""
#define KERN_DEBUG ""
/*
* These can be used to print at the various log levels.
* All of these will print unconditionally, although note that pr_debug()
* and other debug macros are compiled out unless either DEBUG is defined
* or CONFIG_DYNAMIC_DEBUG is set.
*/
#define pr_emerg(fmt, ...) \
printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
#define pr_alert(fmt, ...) \
printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
#define pr_crit(fmt, ...) \
printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
#define pr_err(fmt, ...) \
printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
#define pr_warning(fmt, ...) \
printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
#define pr_warn pr_warning
#define pr_notice(fmt, ...) \
printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
#define pr_info(fmt, ...) \
printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
#define pr_cont(fmt, ...) \
printk(KERN_CONT pr_fmt(fmt), ##__VA_ARGS__)
#define __print_netif_name(dev) (dev)->drv_name[0] ? (dev)->drv_name : "netdev"
#define netdev_printk(lvl, dev, fmt, ...) \
printk("[%s]: " fmt, __print_netif_name(dev), ##__VA_ARGS__)
#define netdev_err(dev, fmt, ...) \
printk("[%s]: " fmt, __print_netif_name(dev), ##__VA_ARGS__)
#define netdev_info(dev, fmt, ...) \
printk("[%s]: " fmt, __print_netif_name(dev), ##__VA_ARGS__)
#define netdev_dbg(dev, fmt, ...) \
printk("[%s]: " fmt, __print_netif_name(dev), ##__VA_ARGS__)
#define netif_err(priv, type, dev, fmt, ...) \
printk("[%s]: " fmt, __print_netif_name(dev), ##__VA_ARGS__)
#define netif_warn(priv, type, dev, fmt, ...) \
printk("[%s]: " fmt, __print_netif_name(dev), ##__VA_ARGS__)
#define netif_notice(priv, type, dev, fmt, ...) \
printk("[%s]: " fmt, __print_netif_name(dev), ##__VA_ARGS__)
#define netif_info(priv, type, dev, fmt, ...) \
printk("[%s]: " fmt, __print_netif_name(dev), ##__VA_ARGS__)
#define netif_dbg(priv, type, dev, fmt, ...) \
printk("[%s]: " fmt, __print_netif_name(dev), ##__VA_ARGS__)
#define dev_err(dev, fmt, ...) \
printk("[dev]: " fmt, ##__VA_ARGS__)
#define dev_info(dev, fmt, ...) \
printk("[dev]: " fmt, ##__VA_ARGS__)
#define dev_alert(dev, fmt, ...) \
printk("[dev]: " fmt, ##__VA_ARGS__)
#ifdef DEBUG
#define might_sleep() assert(can_block(&per_cpu_info[core_id()]))
#define pr_devel(fmt, ...) \
printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#else
#define might_sleep()
#define pr_devel(fmt, ...) \
printd(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#endif
#define pr_debug pr_devel
enum {
NETIF_MSG_DRV = 0x0001,
NETIF_MSG_PROBE = 0x0002,
NETIF_MSG_LINK = 0x0004,
NETIF_MSG_TIMER = 0x0008,
NETIF_MSG_IFDOWN = 0x0010,
NETIF_MSG_IFUP = 0x0020,
NETIF_MSG_RX_ERR = 0x0040,
NETIF_MSG_TX_ERR = 0x0080,
NETIF_MSG_TX_QUEUED = 0x0100,
NETIF_MSG_INTR = 0x0200,
NETIF_MSG_TX_DONE = 0x0400,
NETIF_MSG_RX_STATUS = 0x0800,
NETIF_MSG_PKTDATA = 0x1000,
NETIF_MSG_HW = 0x2000,
NETIF_MSG_WOL = 0x4000,
};
#define MODULE_AUTHOR(...)
#define MODULE_DESCRIPTION(...)
#define MODULE_LICENSE(...)
#define MODULE_VERSION(...)
#define MODULE_FIRMWARE(...)
#define module_param(...)
#define module_param_named(...)
#define MODULE_PARM_DESC(...)
#define MODULE_DEVICE_TABLE(...)
#define THIS_MODULE ((void*)0)
#define EXPORT_SYMBOL(...)
#define __init
#define __exit
#define module_init(...)
#define module_exit(...)
#define is_kdump_kernel() (0)
/* from Linux's ethtool.h. We probably won't use any of this code, but at
* least we can keep it quiet during porting. */
#define SPEED_10 10
#define SPEED_100 100
#define SPEED_1000 1000
#define SPEED_2500 2500
#define SPEED_10000 10000
#define SPEED_20000 20000
#define SPEED_40000 40000
#define SPEED_56000 56000
#define SPEED_UNKNOWN -1
/* Duplex, half or full. */
#define DUPLEX_HALF 0x00
#define DUPLEX_FULL 0x01
#define DUPLEX_UNKNOWN 0xff
#define SUPPORTED_10baseT_Half (1 << 0)
#define SUPPORTED_10baseT_Full (1 << 1)
#define SUPPORTED_100baseT_Half (1 << 2)
#define SUPPORTED_100baseT_Full (1 << 3)
#define SUPPORTED_1000baseT_Half (1 << 4)
#define SUPPORTED_1000baseT_Full (1 << 5)
#define SUPPORTED_Autoneg (1 << 6)
#define SUPPORTED_TP (1 << 7)
#define SUPPORTED_AUI (1 << 8)
#define SUPPORTED_MII (1 << 9)
#define SUPPORTED_FIBRE (1 << 10)
#define SUPPORTED_BNC (1 << 11)
#define SUPPORTED_10000baseT_Full (1 << 12)
#define SUPPORTED_Pause (1 << 13)
#define SUPPORTED_Asym_Pause (1 << 14)
#define SUPPORTED_2500baseX_Full (1 << 15)
#define SUPPORTED_Backplane (1 << 16)
#define SUPPORTED_1000baseKX_Full (1 << 17)
#define SUPPORTED_10000baseKX4_Full (1 << 18)
#define SUPPORTED_10000baseKR_Full (1 << 19)
#define SUPPORTED_10000baseR_FEC (1 << 20)
#define SUPPORTED_20000baseMLD2_Full (1 << 21)
#define SUPPORTED_20000baseKR2_Full (1 << 22)
#define SUPPORTED_40000baseKR4_Full (1 << 23)
#define SUPPORTED_40000baseCR4_Full (1 << 24)
#define SUPPORTED_40000baseSR4_Full (1 << 25)
#define SUPPORTED_40000baseLR4_Full (1 << 26)
#define SUPPORTED_56000baseKR4_Full (1 << 27)
#define SUPPORTED_56000baseCR4_Full (1 << 28)
#define SUPPORTED_56000baseSR4_Full (1 << 29)
#define SUPPORTED_56000baseLR4_Full (1 << 30)
#define ADVERTISED_10baseT_Half (1 << 0)
#define ADVERTISED_10baseT_Full (1 << 1)
#define ADVERTISED_100baseT_Half (1 << 2)
#define ADVERTISED_100baseT_Full (1 << 3)
#define ADVERTISED_1000baseT_Half (1 << 4)
#define ADVERTISED_1000baseT_Full (1 << 5)
#define ADVERTISED_Autoneg (1 << 6)
#define ADVERTISED_TP (1 << 7)
#define ADVERTISED_AUI (1 << 8)
#define ADVERTISED_MII (1 << 9)
#define ADVERTISED_FIBRE (1 << 10)
#define ADVERTISED_BNC (1 << 11)
#define ADVERTISED_10000baseT_Full (1 << 12)
#define ADVERTISED_Pause (1 << 13)
#define ADVERTISED_Asym_Pause (1 << 14)
#define ADVERTISED_2500baseX_Full (1 << 15)
#define ADVERTISED_Backplane (1 << 16)
#define ADVERTISED_1000baseKX_Full (1 << 17)
#define ADVERTISED_10000baseKX4_Full (1 << 18)
#define ADVERTISED_10000baseKR_Full (1 << 19)
#define ADVERTISED_10000baseR_FEC (1 << 20)
#define ADVERTISED_20000baseMLD2_Full (1 << 21)
#define ADVERTISED_20000baseKR2_Full (1 << 22)
#define ADVERTISED_40000baseKR4_Full (1 << 23)
#define ADVERTISED_40000baseCR4_Full (1 << 24)
#define ADVERTISED_40000baseSR4_Full (1 << 25)
#define ADVERTISED_40000baseLR4_Full (1 << 26)
#define ADVERTISED_56000baseKR4_Full (1 << 27)
#define ADVERTISED_56000baseCR4_Full (1 << 28)
#define ADVERTISED_56000baseSR4_Full (1 << 29)
#define ADVERTISED_56000baseLR4_Full (1 << 30)
/* Wake-On-Lan options. */
#define WAKE_PHY (1 << 0)
#define WAKE_UCAST (1 << 1)
#define WAKE_MCAST (1 << 2)
#define WAKE_BCAST (1 << 3)
#define WAKE_ARP (1 << 4)
#define WAKE_MAGIC (1 << 5)
#define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */
/* Enable or disable autonegotiation. */
#define AUTONEG_DISABLE 0x00
#define AUTONEG_ENABLE 0x01
enum ethtool_test_flags {
ETH_TEST_FL_OFFLINE = (1 << 0),
ETH_TEST_FL_FAILED = (1 << 1),
ETH_TEST_FL_EXTERNAL_LB = (1 << 2),
ETH_TEST_FL_EXTERNAL_LB_DONE = (1 << 3),
};
enum ethtool_stringset {
ETH_SS_TEST = 0,
ETH_SS_STATS,
ETH_SS_PRIV_FLAGS,
ETH_SS_NTUPLE_FILTERS,
ETH_SS_FEATURES,
ETH_SS_RSS_HASH_FUNCS,
};
enum {
ETH_RSS_HASH_TOP_BIT, /* Configurable RSS hash function - Toeplitz */
ETH_RSS_HASH_XOR_BIT, /* Configurable RSS hash function - Xor */
ETH_RSS_HASH_FUNCS_COUNT
};
#define __ETH_RSS_HASH_BIT(bit) ((uint32_t)1 << (bit))
#define __ETH_RSS_HASH(name) __ETH_RSS_HASH_BIT(ETH_RSS_HASH_##name##_BIT)
#define ETH_RSS_HASH_TOP __ETH_RSS_HASH(TOP)
#define ETH_RSS_HASH_XOR __ETH_RSS_HASH(XOR)
#define ETH_RSS_HASH_UNKNOWN 0
#define ETH_RSS_HASH_NO_CHANGE 0
/* EEPROM Standards for plug in modules */
#define ETH_MODULE_SFF_8079 0x1
#define ETH_MODULE_SFF_8079_LEN 256
#define ETH_MODULE_SFF_8472 0x2
#define ETH_MODULE_SFF_8472_LEN 512
#define ETH_MODULE_SFF_8636 0x3
#define ETH_MODULE_SFF_8636_LEN 256
#define ETH_MODULE_SFF_8436 0x4
#define ETH_MODULE_SFF_8436_LEN 256
#define ETH_GSTRING_LEN 32
/* ethernet protocol ids. the plan 9 equivalent enum only exists in
* ethermedium.c. */
#define ETH_P_IP 0x0800 /* Internet Protocol packet */
#define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */
#define ETH_P_ARP 0x0806 /* Address Resolution packet */
#define ETH_P_FIP 0x8914 /* FCoE Initialization Protocol */
#define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */
/* Sockaddr structs */
struct sockaddr {
uint16_t sa_family;
char sa_data[14];
};
struct in_addr {
uint32_t s_addr;
};
struct sockaddr_in {
uint16_t sin_family;
uint16_t sin_port;
struct in_addr sin_addr;
uint8_t sin_zero[8]; /* padding */
};
struct in6_addr {
/* this is actually a weird union in glibc */
uint8_t s6_addr[16];
};
struct sockaddr_in6 {
uint16_t sin6_family;
uint16_t sin6_port;
uint32_t sin6_flowinfo;
struct in6_addr sin6_addr;
uint32_t sin6_scope_id;
};
/* Common way to go from netdev (ether / netif) to driver-private ctlr */
static inline void *netdev_priv(struct ether *dev)
{
return dev->ctlr;
}
/* We do our linker table magic and other nonsense. Keeping these around to
* show the code's intent. */
static int register_netdev(struct ether *dev)
{
return 0;
}
static void unregister_netdev(struct ether *dev)
{
}
static void free_netdev(struct ether *dev)
{
}
/* u64 on linux, but a u32 on plan 9. the typedef is probably a good idea */
typedef unsigned int netdev_features_t;
/* Attempted conversions for plan 9 features. For some things, like rx
* checksums, the driver flags the block (e.g. Budpck) to say if a receive
* checksum was already done. There is no flag for saying the device can do
* it. For transmits, the stack needs to know in advance if the device can
* handle the checksum or not. */
#define NETIF_F_RXHASH 0
#define NETIF_F_RXCSUM NETF_RXCSUM
#define NETIF_F_LRO NETF_LRO
#define NETIF_F_GRO 0
#define NETIF_F_LOOPBACK 0
#define NETIF_F_TSO NETF_TSO
#define NETIF_F_SG NETF_SG
#define NETIF_F_IP_CSUM (NETF_IPCK | NETF_UDPCK | NETF_TCPCK)
#define NETIF_F_IPV6_CSUM (NETF_IPCK | NETF_UDPCK | NETF_TCPCK)
#define NETIF_F_GSO_GRE 0
#define NETIF_F_GSO_UDP_TUNNEL 0
#define NETIF_F_GSO_IPIP 0
#define NETIF_F_GSO_SIT 0
#define NETIF_F_TSO_ECN 0
#define NETIF_F_TSO6 0
#define NETIF_F_HW_VLAN_CTAG_TX 0
#define NETIF_F_HIGHDMA 0
#define NETIF_F_HW_VLAN_CTAG_RX 0
#define NETIF_F_TSO_MANGLEID 0
#define NETIF_F_ALL_TSO (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN | NETIF_F_TSO_MANGLEID)
#define netif_msg_drv(p) ((p)->msg_enable & NETIF_MSG_DRV)
#define netif_msg_probe(p) ((p)->msg_enable & NETIF_MSG_PROBE)
#define netif_msg_link(p) ((p)->msg_enable & NETIF_MSG_LINK)
#define netif_msg_timer(p) ((p)->msg_enable & NETIF_MSG_TIMER)
#define netif_msg_ifdown(p) ((p)->msg_enable & NETIF_MSG_IFDOWN)
#define netif_msg_ifup(p) ((p)->msg_enable & NETIF_MSG_IFUP)
#define netif_msg_rx_err(p) ((p)->msg_enable & NETIF_MSG_RX_ERR)
#define netif_msg_tx_err(p) ((p)->msg_enable & NETIF_MSG_TX_ERR)
#define netif_msg_tx_queued(p) ((p)->msg_enable & NETIF_MSG_TX_QUEUED)
#define netif_msg_intr(p) ((p)->msg_enable & NETIF_MSG_INTR)
#define netif_msg_tx_done(p) ((p)->msg_enable & NETIF_MSG_TX_DONE)
#define netif_msg_rx_status(p) ((p)->msg_enable & NETIF_MSG_RX_STATUS)
#define netif_msg_pktdata(p) ((p)->msg_enable & NETIF_MSG_PKTDATA)
#define netif_msg_hw(p) ((p)->msg_enable & NETIF_MSG_HW)
#define netif_msg_wol(p) ((p)->msg_enable & NETIF_MSG_WOL)
static inline uint32_t netif_msg_init(int debug_value,
int default_msg_enable_bits)
{
/* use default */
if (debug_value < 0 || debug_value >= (sizeof(uint32_t) * 8))
return default_msg_enable_bits;
if (debug_value == 0) /* no output */
return 0;
/* set low N bits */
return (1 << debug_value) - 1;
}
enum netdev_state_t {
__LINK_STATE_START,
__LINK_STATE_PRESENT,
__LINK_STATE_NOCARRIER,
__LINK_STATE_LINKWATCH_PENDING,
__LINK_STATE_DORMANT,
};
enum netdev_tx {
__NETDEV_TX_MIN = INT32_MIN, /* make sure enum is signed */
NETDEV_TX_OK = 0x00, /* driver took care of packet */
NETDEV_TX_BUSY = 0x10, /* driver tx path was busy*/
NETDEV_TX_LOCKED = 0x20, /* driver tx lock was already taken */
};
typedef enum netdev_tx netdev_tx_t;
/* Global mutex in linux for "routing netlink". Not sure if we have an
* equivalent or not in Plan 9. */
#define rtnl_lock()
#define rtnl_unlock()
#define ASSERT_RTNL(...)
#define synchronize_irq(x) warn_once("Asked to sync IRQ %d, unsupported", x)
#define HZ 1000
/* Linux has a PCI device id struct. Drivers make tables of their supported
* devices, and this table is handled by higher level systems. We don't have
* those systems, but we probably want the table still for our own parsing. */
struct pci_device_id {
uint32_t vendor, device; /* Vendor and device ID or PCI_ANY_ID*/
uint32_t subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
uint32_t class, class_mask; /* (class,subclass,prog-if) triplet */
unsigned long driver_data; /* Data private to the driver */
};
static const struct pci_device_id *
srch_linux_pci_tbl(const struct pci_device_id *tbl, struct pci_device *needle)
{
const struct pci_device_id *i;
for (i = tbl; i->vendor; i++) {
if ((needle->ven_id == i->vendor) && (needle->dev_id ==
i->device))
break;
}
if (i->vendor)
return i;
return 0;
}
#define PCI_ANY_ID (~0)
/* This macro is used in setting device_id entries */
#define PCI_VDEVICE(vend, dev) \
.vendor = PCI_VENDOR_ID_##vend, .device = (dev), \
.subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, 0, 0
#define PCI_DEVICE(vend, dev) \
.vendor = (vend), .device = (dev), \
.subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID
/* Linux also has its own table of vendor ids. We have the pci_defs table, but
* this is a bootstrap issue. */
#define PCI_VENDOR_ID_BROADCOM 0x14e4
#define PCI_VENDOR_ID_REALTEK 0x10ec
#define PCI_VENDOR_ID_DLINK 0x1186
#define PCI_VENDOR_ID_AT 0x1259
#define PCI_VENDOR_ID_LINKSYS 0x1737
#define PCI_VENDOR_ID_GIGABYTE 0x1458
/* I'd like to spatch all of the pci methods, but I don't know how to do the
* reads. Since we're not doing the reads, then no sense doing the writes. */
static inline int pci_read_config_byte(struct pci_device *dev, uint32_t off,
uint8_t *val)
{
*val = pcidev_read8(dev, off);
return 0;
}
static inline int pci_read_config_word(struct pci_device *dev, uint32_t off,
uint16_t *val)
{
*val = pcidev_read16(dev, off);
return 0;
}
static inline int pci_read_config_dword(struct pci_device *dev, uint32_t off,
uint32_t *val)
{
*val = pcidev_read32(dev, off);
return 0;
}
static inline int pci_write_config_byte(struct pci_device *dev, uint32_t off,
uint8_t val)
{
pcidev_write8(dev, off, val);
return 0;
}
static inline int pci_write_config_word(struct pci_device *dev, uint32_t off,
uint16_t val)
{
pcidev_write16(dev, off, val);
return 0;
}
static inline int pci_write_config_dword(struct pci_device *dev, uint32_t off,
uint32_t val)
{
pcidev_write32(dev, off, val);
return 0;
}
static inline void pci_disable_device(struct pci_device *dev)
{
pci_clr_bus_master(dev);
}
static inline int pci_enable_device(struct pci_device *dev)
{
pci_set_bus_master(dev);
return 0;
}
static inline uint32_t pci_resource_len(struct pci_device *dev, int bir)
{
return pci_get_membar_sz(dev, bir);
}
static inline void *pci_resource_start(struct pci_device *dev, int bir)
{
return (void*)pci_get_membar(dev, bir);
}
static inline void *pci_resource_end(struct pci_device *dev, int bir)
{
return (void*)(pci_get_membar(dev, bir) + pci_resource_len(dev, bir));
}
#define IORESOURCE_TYPE_BITS 0x00001f00 /* Resource type */
#define IORESOURCE_IO 0x00000100 /* PCI/ISA I/O ports */
#define IORESOURCE_MEM 0x00000200
static inline int pci_resource_flags(struct pci_device *pdev, int bir)
{
return pci_get_membar(pdev, bir) ? IORESOURCE_MEM : IORESOURCE_IO;
}
/* Linux stores this in the device to avoid lookups, which we can consider. */
static bool pci_is_pcie(struct pci_device *dev)
{
return pci_find_cap(dev, PCI_CAP_ID_EXP, NULL) == 0 ? TRUE : FALSE;
}
/* Hacked up version of Linux's. Assuming reg's are implemented and
* read_config never fails. */
static int pcie_capability_read_word(struct pci_device *dev, int pos,
uint16_t *val)
{
uint32_t pcie_cap;
*val = 0;
if (pos & 1)
return -EINVAL;
if (pci_find_cap(dev, PCI_CAP_ID_EXP, &pcie_cap))
return -EINVAL;
pci_read_config_word(dev, pcie_cap + pos, val);
return 0;
}
static int pcie_capability_write_word(struct pci_device *dev, int pos,
uint16_t val)
{
uint32_t pcie_cap;
if (pos & 3)
return -EINVAL;
if (pci_find_cap(dev, PCI_CAP_ID_EXP, &pcie_cap))
return -EINVAL;
pci_write_config_word(dev, pcie_cap + pos, val);
return 0;
}
static int pcie_capability_clear_and_set_word(struct pci_device *dev, int pos,
uint16_t clear, uint16_t set)
{
int ret;
uint16_t val;
ret = pcie_capability_read_word(dev, pos, &val);
if (ret)
return ret;
val &= ~clear;
val |= set;
return pcie_capability_write_word(dev, pos, val);
}
static int pcie_capability_clear_word(struct pci_device *dev, int pos,
uint16_t clear)
{
return pcie_capability_clear_and_set_word(dev, pos, clear, 0);
}
static int pcie_capability_set_word(struct pci_device *dev, int pos,
uint16_t set)
{
return pcie_capability_clear_and_set_word(dev, pos, 0, set);
}
/* Faking it */
static int pci_request_regions(struct pci_device *pdev, const char *res_name)
{
return 0;
}
static void pci_release_regions(struct pci_device *pdev)
{
}
static bool pci_dev_run_wake(struct pci_device *dev)
{
return FALSE;
}
#define ioremap_nocache(paddr, sz) \
(void*)vmap_pmem_nocache((uintptr_t)paddr, sz)
#define ioremap(paddr, sz) (void*)vmap_pmem((uintptr_t)paddr, sz)
#define pci_ioremap_bar(dev, bir) (void*)pci_map_membar(dev, bir)
#define pci_disable_link_state(...)
#define dev_addr_add(dev, addr, type) ({memcpy((dev)->ea, addr, Eaddrlen); 0;})
#define dev_addr_del(...)
/* Some of these might be important. Mostly we need to rewrite whatever is
* using them, but we can leave the functions around to remind us what the code
* is supposed to do, especially for things we don't support yet. */
#define SET_NETDEV_DEV(...)
/* May need to do something with edev's queues or flags. */
#define netif_tx_wake_all_queues(...)
#define netif_tx_wake_queue(...)
#define netif_tx_start_all_queues(...)
#define netif_tx_start_queue(...)
#define netif_tx_stop_queue(...)
#define netif_start_queue(...)
#define netif_stop_queue(...)
#define netif_wake_queue(...)
#define netif_device_detach(...)
#define netif_queue_stopped(...) (FALSE)
#define netif_napi_add(...)
#define netif_napi_del(...)
#define napi_hash_add(...)
#define napi_enable(...)
#define napi_disable(...)
#define napi_schedule(...)
#define napi_schedule_irqoff(...)
#define napi_complete(...)
#define free_irq(...) /* We don't free yet! */
/* picks a random, valid mac addr for dev */
#define eth_hw_addr_random(...)
/* checks if the MAC is not 0 and not multicast (all 1s) */
#define is_valid_ether_addr(...) (TRUE)
/* The flag this checks is set on before open. Turned off on failure, etc. */
#define netif_running(dev) (TRUE)
#define netdev_tx_sent_queue(...)
#define netdev_update_features(...)
#define skb_tx_timestamp(...)
#define net_ratelimit() (TRUE)
#define NET_SKB_PAD 0 /* padding for SKBs. Ignoring it for now */
#define MAX_SKB_FRAGS 16 /* we'll probably delete code using this */
#define VLAN_VID_MASK 0x0fff /* VLAN Identifier */
/* Could spatch this:
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
to:
if (!pci_get_membar(pdev, 0)) {
eth_zero_addr(bp->dev->ea);
to:
memset(bp->dev->ea, 0, Eaddrlen);
*/
struct firmware {
const uint8_t *data;
size_t size;
};
static inline int request_firmware(const struct firmware **fwp,
const char *file_name,
struct device *ignored)
{
struct firmware *ret_fw;
struct file_or_chan *fw_file;
void *fw_data;
char dirname[] = "/lib/firmware/";
/* could dynamically allocate the min of this and some MAX */
char fullpath[sizeof(dirname) + strlen(file_name) + 1];
snprintf(fullpath, sizeof(fullpath), "%s%s", dirname, file_name);
fw_file = foc_open(fullpath, O_READ, 0);
if (!fw_file) {
printk("Unable to find firmware file %s!\n", fullpath);
return -1;
}
fw_data = kread_whole_file(fw_file);
if (!fw_data) {
printk("Unable to load firmware file %s!\n", fullpath);
foc_decref(fw_file);
return -1;
}
ret_fw = kmalloc(sizeof(struct firmware), MEM_WAIT);
ret_fw->data = fw_data;
ret_fw->size = foc_get_len(fw_file);
*fwp = ret_fw;
foc_decref(fw_file);
return 0;
}
static inline void release_firmware(const struct firmware *fw)
{
if (fw) {
kfree((void*)fw->data);
kfree((void*)fw);
}
}
static inline uint32_t ethtool_rxfh_indir_default(uint32_t index,
uint32_t n_rx_rings)
{
return index % n_rx_rings;
}
/* Plan 9 does a memcmp for this. We should probably have a helper, like for
* IP addrs. */
static inline bool ether_addr_equal(const uint8_t *addr1, const uint8_t *addr2)
{
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
uint32_t fold = ((*(const uint32_t *)addr1) ^ (*(const uint32_t *)addr2)) |
((*(const uint16_t *)(addr1 + 4)) ^ (*(const uint16_t *)(addr2 + 4)));
return fold == 0;
#else
const uint16_t *a = (const uint16_t *)addr1;
const uint16_t *b = (const uint16_t *)addr2;
return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) == 0;
#endif
}
/* Linux uses this interface for 64 bit stats on 32 bit machines. We're 64 bit
* only, so we can ignore the 32 bit versions. */
struct u64_stats_sync {
};
static inline void u64_stats_init(struct u64_stats_sync *syncp)
{
}
static inline void u64_stats_update_begin(struct u64_stats_sync *syncp)
{
}
static inline void u64_stats_update_end(struct u64_stats_sync *syncp)
{
}
static inline void u64_stats_update_begin_raw(struct u64_stats_sync *syncp)
{
}
static inline void u64_stats_update_end_raw(struct u64_stats_sync *syncp)
{
}
static inline unsigned int
__u64_stats_fetch_begin(const struct u64_stats_sync *syncp)
{
return 0;
}
static inline unsigned int
u64_stats_fetch_begin(const struct u64_stats_sync *syncp)
{
return __u64_stats_fetch_begin(syncp);
}
static inline bool __u64_stats_fetch_retry(const struct u64_stats_sync *syncp,
unsigned int start)
{
return false;
}
static inline bool u64_stats_fetch_retry(const struct u64_stats_sync *syncp,
unsigned int start)
{
return __u64_stats_fetch_retry(syncp, start);
}
static inline unsigned int
u64_stats_fetch_begin_irq(const struct u64_stats_sync *syncp)
{
return __u64_stats_fetch_begin(syncp);
}
static inline bool u64_stats_fetch_retry_irq(const struct u64_stats_sync *syncp,
unsigned int start)
{
return __u64_stats_fetch_retry(syncp, start);
}
#define pm_request_resume(...) (1)
#define pm_schedule_suspend(...) (-ENOSYS)
#define pm_runtime_get_noresume(...)
#define pm_runtime_active(...) (true)
#define pm_runtime_put_noidle(...)
#define pm_runtime_get_sync(...) (1)
#define pm_runtime_put_sync(...) (-ENOSYS)
#define device_set_wakeup_enable(...) (-EINVAL)
#include <linux/compat_todo.h>