⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hifn7751.c

📁 linux下基于加密芯片的加密设备
💻 C
📖 第 1 页 / 共 5 页
字号:
/*	$OpenBSD: hifn7751.c,v 1.120 2002/05/17 00:33:34 deraadt Exp $	*//* * Invertex AEON / Hifn 7751 driver * Copyright (c) 1999 Invertex Inc. All rights reserved. * Copyright (c) 1999 Theo de Raadt * Copyright (c) 2000-2001 Network Security Technologies, Inc. *			http://www.netsec.net * Copyright (c) 2003 Hifn Inc. * * This driver is based on a previous driver by Invertex, for which they * requested:  Please send any comments, feedback, bug-fixes, or feature * requests to software@invertex.com. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *   notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *   notice, this list of conditions and the following disclaimer in the *   documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products *   derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Effort sponsored in part by the Defense Advanced Research Projects * Agency (DARPA) and Air Force Research Laboratory, Air Force * Materiel Command, USAF, under agreement number F30602-01-2-0537. * *__FBSDID("$FreeBSD: src/sys/dev/hifn/hifn7751.c,v 1.30 2004/10/15 03:54:56 sam Exp $"); *//* * Driver for various Hifn encryption processors. */#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/list.h>#include <linux/slab.h>#include <linux/wait.h>#include <linux/sched.h>#include <linux/pci.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/spinlock.h>#include <linux/random.h>#include <asm/io.h>#include <cryptodev.h>#include <uio.h>#include <hifn/hifn7751reg.h>#include <hifn/hifn7751var.h>#define KASSERT(c,p)	if (!(c)) { printk p ; } else#if 1#define	DPRINTF(a...)	if (debug) { printk("hifn: " a); } else#else#define	DPRINTF(a...)#endif#define device_printf(dev, a...) printk("hifn: " a)#define DELAY(x)	udelay(x)#define bcopy(s,d,l)			memcpy(d,s,l)#define bzero(p,l)				memset(p,0,l)#define bcmp(x, y, l)			memcmp(x,y,l)#define read_random(p,l) get_random_bytes(p,l)#define htole32(x) cpu_to_le32(x)#define htole16(x) cpu_to_le16(x)#define MIN(x,y)	((x) < (y) ? (x) : (y))#define pci_get_vendor(dev)	((dev)->vendor)#define pci_get_device(dev)	((dev)->device)static inline intpci_get_revid(struct pci_dev *dev){	u8 rid = 0;	pci_read_config_byte(dev, PCI_REVISION_ID, &rid);	return rid;}static	struct hifn_stats hifnstats;#define	hifn_debug debugstatic	int debug = 0;MODULE_PARM(debug, "i");MODULE_PARM_DESC(debug, "Enable debug");static	int hifn_maxbatch = 1;MODULE_PARM(hifn_maxbatch, "i");MODULE_PARM_DESC(hifn_maxbatch, "max ops to batch w/o interrupt");/* * Prototypes and count for the pci_device structure */static	int  hifn_probe(struct pci_dev *dev, const struct pci_device_id *ent);static	void hifn_remove(struct pci_dev *dev);static	void hifn_reset_board(struct hifn_softc *, int);static	void hifn_reset_puc(struct hifn_softc *);static	void hifn_puc_wait(struct hifn_softc *);static	int hifn_enable_crypto(struct hifn_softc *);static	void hifn_set_retry(struct hifn_softc *sc);static	void hifn_init_dma(struct hifn_softc *);static	void hifn_init_pci_registers(struct hifn_softc *);static	int hifn_sramsize(struct hifn_softc *);static	int hifn_dramsize(struct hifn_softc *);static	int hifn_ramtype(struct hifn_softc *);static	void hifn_sessions(struct hifn_softc *);static irqreturn_t hifn_intr(int irq, void *arg, struct pt_regs *regs);static	u_int hifn_write_command(struct hifn_command *, u_int8_t *);static	u_int32_t hifn_next_signature(u_int32_t a, u_int cnt);static	int hifn_newsession(void *, u_int32_t *, struct cryptoini *);static	int hifn_freesession(void *, u_int64_t);static	int hifn_process(void *, struct cryptop *, int);static	void hifn_callback(struct hifn_softc *, struct hifn_command *, u_int8_t *);static	int hifn_crypto(struct hifn_softc *, struct hifn_command *, struct cryptop *, int);static	int hifn_readramaddr(struct hifn_softc *, int, u_int8_t *);static	int hifn_writeramaddr(struct hifn_softc *, int, u_int8_t *);static	int hifn_dmamap_load_src(struct hifn_softc *, struct hifn_command *);static	int hifn_dmamap_load_dst(struct hifn_softc *, struct hifn_command *);static	int hifn_init_pubrng(struct hifn_softc *);static	void hifn_rng(unsigned long arg);static	void hifn_tick(unsigned long arg);static	void hifn_abort(struct hifn_softc *);static	void hifn_alloc_slot(struct hifn_softc *, int *, int *, int *, int *);static	void hifn_write_reg_0(struct hifn_softc *, bus_size_t, u_int32_t);static	void hifn_write_reg_1(struct hifn_softc *, bus_size_t, u_int32_t);static __inline u_int32_tREAD_REG_0(struct hifn_softc *sc, bus_size_t reg){    u_int32_t v = readl(sc->sc_bar0 + reg);    sc->sc_bar0_lastreg = (bus_size_t) -1;    return (v);}#define	WRITE_REG_0(sc, reg, val)	hifn_write_reg_0(sc, reg, val)static __inline u_int32_tREAD_REG_1(struct hifn_softc *sc, bus_size_t reg){    u_int32_t v = readl(sc->sc_bar1 + reg);    sc->sc_bar1_lastreg = (bus_size_t) -1;    return (v);}#define	WRITE_REG_1(sc, reg, val)	hifn_write_reg_1(sc, reg, val)/* * map in a given buffer (great on some arches :-) */static intpci_map_uio(struct hifn_softc *sc, struct hifn_operand *buf, struct uio *uio){	struct iovec *iov = uio->uio_iov;	DPRINTF("%s()\n", __FUNCTION__);	buf->mapsize = 0;	for (buf->nsegs = 0; buf->nsegs < uio->uio_iovcnt; ) {		buf->segs[buf->nsegs].ds_addr = pci_map_single(sc->sc_dev,				iov->iov_base, iov->iov_len,				PCI_DMA_BIDIRECTIONAL);		buf->segs[buf->nsegs].ds_len = iov->iov_len;		buf->mapsize += iov->iov_len;		iov++;		buf->nsegs++;	}	/* identify this buffer by the first segment */	buf->map = (void *) buf->segs[0].ds_addr;	return(0);}static voidpci_sync_iov(struct hifn_softc *sc, struct hifn_operand *buf){	int i;	DPRINTF("%s()\n", __FUNCTION__);	for (i = 0; i < buf->nsegs; i++)		pci_dma_sync_single(sc->sc_dev, buf->segs[i].ds_addr,				buf->segs[i].ds_len, PCI_DMA_BIDIRECTIONAL);}static voidpci_unmap_iov(struct hifn_softc *sc, struct hifn_operand *buf){	int i;	DPRINTF("%s()\n", __FUNCTION__);	for (i = 0; i < buf->nsegs; i++) {		pci_unmap_single(sc->sc_dev, buf->segs[i].ds_addr,				buf->segs[i].ds_len, PCI_DMA_BIDIRECTIONAL);		buf->segs[i].ds_addr = 0;		buf->segs[i].ds_len = 0;	}	buf->nsegs = 0;	buf->mapsize = 0;	buf->map = 0;}static const char*hifn_partname(struct hifn_softc *sc){	/* XXX sprintf numbers when not decoded */	switch (pci_get_vendor(sc->sc_dev)) {	case PCI_VENDOR_HIFN:		switch (pci_get_device(sc->sc_dev)) {		case PCI_PRODUCT_HIFN_6500:	return "Hifn 6500";		case PCI_PRODUCT_HIFN_7751:	return "Hifn 7751";		case PCI_PRODUCT_HIFN_7811:	return "Hifn 7811";		case PCI_PRODUCT_HIFN_7951:	return "Hifn 7951";		case PCI_PRODUCT_HIFN_7955:	return "Hifn 7955";		case PCI_PRODUCT_HIFN_7956:	return "Hifn 7956";		}		return "Hifn unknown-part";	case PCI_VENDOR_INVERTEX:		switch (pci_get_device(sc->sc_dev)) {		case PCI_PRODUCT_INVERTEX_AEON:	return "Invertex AEON";		}		return "Invertex unknown-part";	case PCI_VENDOR_NETSEC:		switch (pci_get_device(sc->sc_dev)) {		case PCI_PRODUCT_NETSEC_7751:	return "NetSec 7751";		}		return "NetSec unknown-part";	}	return "Unknown-vendor unknown-part";}/* * Attach an interface that successfully probed. */static inthifn_probe(struct pci_dev *dev, const struct pci_device_id *ent){	struct hifn_softc *sc;	char rbase;	u_int16_t ena, rev;	int rseg, rc, mem_start, mem_len;	static int num_chips = 0;	DPRINTF("%s()\n", __FUNCTION__);	if (pci_enable_device(dev) < 0)		return(-ENODEV);	if (!dev->irq) {		printk("hifn: found device with no IRQ assigned. check BIOS settings!");		pci_disable_device(dev);		return(-ENODEV);	}	sc = (struct hifn_softc *) kmalloc(sizeof(*sc), GFP_KERNEL);	if (!sc)		return(-ENOMEM);	memset(sc, 0, sizeof(*sc));	sc->sc_dev = dev;	sc->sc_irq = -1;	sc->sc_cid = -1;	sc->sc_num = num_chips++;	pci_set_drvdata(sc->sc_dev, sc);	spin_lock_init(&sc->sc_mtx);	/* XXX handle power management */	/*	 * The 7951 and 795x have a random number generator and	 * public key support; note this.	 */	if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&	    (pci_get_device(dev) == PCI_PRODUCT_HIFN_7951 ||	     pci_get_device(dev) == PCI_PRODUCT_HIFN_7955 ||	     pci_get_device(dev) == PCI_PRODUCT_HIFN_7956))		sc->sc_flags = HIFN_HAS_RNG | HIFN_HAS_PUBLIC;	/*	 * The 7811 has a random number generator and	 * we also note it's identity 'cuz of some quirks.	 */	if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&	    pci_get_device(dev) == PCI_PRODUCT_HIFN_7811)		sc->sc_flags |= HIFN_IS_7811 | HIFN_HAS_RNG;	/*	 * The 795x parts support AES.	 */	if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&	    (pci_get_device(dev) == PCI_PRODUCT_HIFN_7955 ||	     pci_get_device(dev) == PCI_PRODUCT_HIFN_7956))		sc->sc_flags |= HIFN_IS_7956 | HIFN_HAS_AES;	/*	 * Setup PCI resources. Note that we record the bus	 * tag and handle for each register mapping, this is	 * used by the READ_REG_0, WRITE_REG_0, READ_REG_1,	 * and WRITE_REG_1 macros throughout the driver.	 */	mem_start = pci_resource_start(sc->sc_dev, 0);	mem_len   = pci_resource_len(sc->sc_dev, 0);	sc->sc_bar0 = (unsigned long) ioremap(mem_start, mem_len);	if (!sc->sc_bar0) {		device_printf(dev, "cannot map bar%d register space\n", 0);		goto fail;	}	sc->sc_bar0_lastreg = (bus_size_t) -1;	mem_start = pci_resource_start(sc->sc_dev, 1);	mem_len   = pci_resource_len(sc->sc_dev, 1);	sc->sc_bar1 = (unsigned long) ioremap(mem_start, mem_len);	if (!sc->sc_bar1) {		device_printf(dev, "cannot map bar%d register space\n", 1);		goto fail;	}	sc->sc_bar1_lastreg = (bus_size_t) -1;	hifn_set_retry(sc);	/*	 * Setup the area where the Hifn DMA's descriptors	 * and associated data structures.	 */	sc->sc_dma = (struct hifn_dma *) pci_alloc_consistent(dev,			sizeof(*sc->sc_dma),			&sc->sc_dma_physaddr);	if (!sc->sc_dma) {		device_printf(dev, "cannot alloc sc_dma\n");		goto fail;	}	bzero(sc->sc_dma, sizeof(*sc->sc_dma));	/*	 * Reset the board and do the ``secret handshake''	 * to enable the crypto support.  Then complete the	 * initialization procedure by setting up the interrupt	 * and hooking in to the system crypto support so we'll	 * get used for system services like the crypto device,	 * IPsec, RNG device, etc.	 */	hifn_reset_board(sc, 0);	if (hifn_enable_crypto(sc) != 0) {		device_printf(dev, "crypto enabling failed\n");		goto fail;	}	hifn_reset_puc(sc);	hifn_init_dma(sc);	hifn_init_pci_registers(sc);	pci_set_master(sc->sc_dev);	/* XXX can't dynamically determine ram type for 795x; force dram */	if (sc->sc_flags & HIFN_IS_7956)		sc->sc_drammodel = 1;	else if (hifn_ramtype(sc))		goto fail;	if (sc->sc_drammodel == 0)		hifn_sramsize(sc);	else		hifn_dramsize(sc);	/*	 * Workaround for NetSec 7751 rev A: half ram size because two	 * of the address lines were left floating	 */	if (pci_get_vendor(dev) == PCI_VENDOR_NETSEC &&	    pci_get_device(dev) == PCI_PRODUCT_NETSEC_7751 &&	    pci_get_revid(dev) == 0x61)	/*XXX???*/		sc->sc_ramsize >>= 1;	/*	 * Arrange the interrupt line.	 */	rc = request_irq(dev->irq, hifn_intr, SA_SHIRQ, "hifn", sc);	if (rc) {		device_printf(dev, "could not map interrupt: %d\n", rc);		goto fail;	}	sc->sc_irq = dev->irq;	hifn_sessions(sc);	/*	 * NB: Keep only the low 16 bits; this masks the chip id	 *     from the 7951.	 */	rev = READ_REG_1(sc, HIFN_1_REVID) & 0xffff;	rseg = sc->sc_ramsize / 1024;	rbase = 'K';	if (sc->sc_ramsize >= (1024 * 1024)) {		rbase = 'M';		rseg /= 1024;	}	device_printf(sc->sc_dev, "%s, rev %u, %d%cB %cram\n",		hifn_partname(sc), rev,		rseg, rbase, sc->sc_drammodel ? 'd' : 's');	sc->sc_cid = crypto_get_driverid(0);	if (sc->sc_cid < 0) {		device_printf(dev, "could not get crypto driver id\n");		goto fail;	}	WRITE_REG_0(sc, HIFN_0_PUCNFG,	    READ_REG_0(sc, HIFN_0_PUCNFG) | HIFN_PUCNFG_CHIPID);	ena = READ_REG_0(sc, HIFN_0_PUSTAT) & HIFN_PUSTAT_CHIPENA;	switch (ena) {	case HIFN_PUSTAT_ENA_2:		crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0,		    hifn_newsession, hifn_freesession, hifn_process, sc);		crypto_register(sc->sc_cid, CRYPTO_ARC4, 0, 0,		    hifn_newsession, hifn_freesession, hifn_process, sc);		if (sc->sc_flags & HIFN_HAS_AES)			crypto_register(sc->sc_cid, CRYPTO_AES_CBC,  0, 0,				hifn_newsession, hifn_freesession,				hifn_process, sc);		/*FALLTHROUGH*/	case HIFN_PUSTAT_ENA_1:		crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0,		    hifn_newsession, hifn_freesession, hifn_process, sc);		crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0,		    hifn_newsession, hifn_freesession, hifn_process, sc);		crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0,		    hifn_newsession, hifn_freesession, hifn_process, sc);		crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0,		    hifn_newsession, hifn_freesession, hifn_process, sc);		crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0,		    hifn_newsession, hifn_freesession, hifn_process, sc);		break;	}	if (sc->sc_flags & (HIFN_HAS_PUBLIC | HIFN_HAS_RNG))		hifn_init_pubrng(sc);	init_timer(&sc->sc_tickto);	sc->sc_tickto.function = hifn_tick;	sc->sc_tickto.data = (unsigned long) sc;	mod_timer(&sc->sc_tickto, jiffies + HZ);	return (0);fail:    if (sc->sc_cid >= 0)        crypto_unregister_all(sc->sc_cid);    if (sc->sc_irq != -1)        free_irq(sc->sc_irq, sc);    if (sc->sc_dma) {		/* Turn off DMA polling */		WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |			HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);        pci_free_consistent(sc->sc_dev,				sizeof(*sc->sc_dma),                sc->sc_dma, sc->sc_dma_physaddr);	}    kfree(sc);	return (-ENXIO);}/* * Detach an interface that successfully probed. */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -