123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- /*-
- * Driver for Hifn HIPP-I/II chipset
- * Copyright (c) 2006 Michael Richardson <mcr@xelerance.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 by Hifn Inc.
- *
- */
- /*
- * Driver for various Hifn encryption processors.
- */
- #include <linux/version.h>
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38) && !defined(AUTOCONF_INCLUDED)
- #include <linux/config.h>
- #endif
- #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 <linux/skbuff.h>
- #include <linux/uio.h>
- #include <linux/sysfs.h>
- #include <linux/miscdevice.h>
- #include <asm/io.h>
- #include <cryptodev.h>
- #include "hifnHIPPreg.h"
- #include "hifnHIPPvar.h"
- #if 1
- #define DPRINTF(a...) if (hipp_debug) { \
- printk("%s: ", sc ? \
- device_get_nameunit(sc->sc_dev) : "hifn"); \
- printk(a); \
- } else
- #else
- #define DPRINTF(a...)
- #endif
- typedef int bus_size_t;
- static inline int
- pci_get_revid(struct pci_dev *dev)
- {
- u8 rid = 0;
- pci_read_config_byte(dev, PCI_REVISION_ID, &rid);
- return rid;
- }
- #define debug hipp_debug
- int hipp_debug = 0;
- module_param(hipp_debug, int, 0644);
- MODULE_PARM_DESC(hipp_debug, "Enable debug");
- int hipp_maxbatch = 1;
- module_param(hipp_maxbatch, int, 0644);
- MODULE_PARM_DESC(hipp_maxbatch, "max ops to batch w/o interrupt");
- static int hipp_probe(struct pci_dev *dev, const struct pci_device_id *ent);
- static void hipp_remove(struct pci_dev *dev);
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
- static irqreturn_t hipp_intr(int irq, void *arg);
- #else
- static irqreturn_t hipp_intr(int irq, void *arg, struct pt_regs *regs);
- #endif
- static int hipp_num_chips = 0;
- static struct hipp_softc *hipp_chip_idx[HIPP_MAX_CHIPS];
- static int hipp_newsession(device_t, u_int32_t *, struct cryptoini *);
- static int hipp_freesession(device_t, u_int64_t);
- static int hipp_process(device_t, struct cryptop *, int);
- static device_method_t hipp_methods = {
- /* crypto device methods */
- DEVMETHOD(cryptodev_newsession, hipp_newsession),
- DEVMETHOD(cryptodev_freesession,hipp_freesession),
- DEVMETHOD(cryptodev_process, hipp_process),
- };
- static __inline u_int32_t
- READ_REG(struct hipp_softc *sc, unsigned int barno, bus_size_t reg)
- {
- u_int32_t v = readl(sc->sc_bar[barno] + reg);
- //sc->sc_bar0_lastreg = (bus_size_t) -1;
- return (v);
- }
- static __inline void
- WRITE_REG(struct hipp_softc *sc, unsigned int barno, bus_size_t reg, u_int32_t val)
- {
- writel(val, sc->sc_bar[barno] + reg);
- }
- #define READ_REG_0(sc, reg) READ_REG(sc, 0, reg)
- #define WRITE_REG_0(sc, reg, val) WRITE_REG(sc,0, reg, val)
- #define READ_REG_1(sc, reg) READ_REG(sc, 1, reg)
- #define WRITE_REG_1(sc, reg, val) WRITE_REG(sc,1, reg, val)
- static int
- hipp_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
- {
- return EINVAL;
- }
- static int
- hipp_freesession(device_t dev, u_int64_t tid)
- {
- return EINVAL;
- }
- static int
- hipp_process(device_t dev, struct cryptop *crp, int hint)
- {
- return EINVAL;
- }
- static const char*
- hipp_partname(struct hipp_softc *sc, char buf[128], size_t blen)
- {
- char *n = NULL;
- switch (pci_get_vendor(sc->sc_pcidev)) {
- case PCI_VENDOR_HIFN:
- switch (pci_get_device(sc->sc_pcidev)) {
- case PCI_PRODUCT_HIFN_7855: n = "Hifn 7855";
- case PCI_PRODUCT_HIFN_8155: n = "Hifn 8155";
- case PCI_PRODUCT_HIFN_6500: n = "Hifn 6500";
- }
- }
- if(n==NULL) {
- snprintf(buf, blen, "VID=%02x,PID=%02x",
- pci_get_vendor(sc->sc_pcidev),
- pci_get_device(sc->sc_pcidev));
- } else {
- buf[0]='\0';
- strncat(buf, n, blen);
- }
- return buf;
- }
- struct hipp_fs_entry {
- struct attribute attr;
- /* other stuff */
- };
- static ssize_t
- cryptoid_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
- {
- struct hipp_softc *sc;
- sc = pci_get_drvdata(to_pci_dev (dev));
- return sprintf (buf, "%d\n", sc->sc_cid);
- }
- struct device_attribute hipp_dev_cryptoid = __ATTR_RO(cryptoid);
- /*
- * Attach an interface that successfully probed.
- */
- static int
- hipp_probe(struct pci_dev *dev, const struct pci_device_id *ent)
- {
- struct hipp_softc *sc = NULL;
- int i;
- //char rbase;
- //u_int16_t ena;
- int rev;
- //int rseg;
- int rc;
- DPRINTF("%s()\n", __FUNCTION__);
- if (pci_enable_device(dev) < 0)
- return(-ENODEV);
- if (pci_set_mwi(dev))
- return(-ENODEV);
- if (!dev->irq) {
- printk("hifn: found device with no IRQ assigned. check BIOS settings!");
- pci_disable_device(dev);
- return(-ENODEV);
- }
- sc = (struct hipp_softc *) kmalloc(sizeof(*sc), GFP_KERNEL);
- if (!sc)
- return(-ENOMEM);
- memset(sc, 0, sizeof(*sc));
- softc_device_init(sc, "hifn-hipp", hipp_num_chips, hipp_methods);
- sc->sc_pcidev = dev;
- sc->sc_irq = -1;
- sc->sc_cid = -1;
- sc->sc_num = hipp_num_chips++;
- if (sc->sc_num < HIPP_MAX_CHIPS)
- hipp_chip_idx[sc->sc_num] = sc;
- pci_set_drvdata(sc->sc_pcidev, sc);
- spin_lock_init(&sc->sc_mtx);
- /*
- * Setup PCI resources.
- * The READ_REG_0, WRITE_REG_0, READ_REG_1,
- * and WRITE_REG_1 macros throughout the driver are used
- * to permit better debugging.
- */
- for(i=0; i<4; i++) {
- unsigned long mem_start, mem_len;
- mem_start = pci_resource_start(sc->sc_pcidev, i);
- mem_len = pci_resource_len(sc->sc_pcidev, i);
- sc->sc_barphy[i] = (caddr_t)mem_start;
- sc->sc_bar[i] = (ocf_iomem_t) ioremap(mem_start, mem_len);
- if (!sc->sc_bar[i]) {
- device_printf(sc->sc_dev, "cannot map bar%d register space\n", i);
- goto fail;
- }
- }
- //hipp_reset_board(sc, 0);
- pci_set_master(sc->sc_pcidev);
- /*
- * Arrange the interrupt line.
- */
- rc = request_irq(dev->irq, hipp_intr, IRQF_SHARED, "hifn", sc);
- if (rc) {
- device_printf(sc->sc_dev, "could not map interrupt: %d\n", rc);
- goto fail;
- }
- sc->sc_irq = dev->irq;
- rev = READ_REG_1(sc, HIPP_1_REVID) & 0xffff;
- {
- char b[32];
- device_printf(sc->sc_dev, "%s, rev %u",
- hipp_partname(sc, b, sizeof(b)), rev);
- }
- #if 0
- if (sc->sc_flags & HIFN_IS_7956)
- printf(", pll=0x%x<%s clk, %ux mult>",
- sc->sc_pllconfig,
- sc->sc_pllconfig & HIFN_PLL_REF_SEL ? "ext" : "pci",
- 2 + 2*((sc->sc_pllconfig & HIFN_PLL_ND) >> 11));
- #endif
- printf("\n");
- sc->sc_cid = crypto_get_driverid(softc_get_device(sc),CRYPTOCAP_F_HARDWARE);
- if (sc->sc_cid < 0) {
- device_printf(sc->sc_dev, "could not get crypto driver id\n");
- goto fail;
- }
- #if 0 /* cannot work with a non-GPL module */
- /* make a sysfs entry to let the world know what entry we got */
- sysfs_create_file(&sc->sc_pcidev->dev.kobj, &hipp_dev_cryptoid.attr);
- #endif
- #if 0
- init_timer(&sc->sc_tickto);
- sc->sc_tickto.function = hifn_tick;
- sc->sc_tickto.data = (unsigned long) sc->sc_num;
- mod_timer(&sc->sc_tickto, jiffies + HZ);
- #endif
- #if 0 /* no code here yet ?? */
- crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
- #endif
- 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 0
- 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_pcidev,
- sizeof(*sc->sc_dma),
- sc->sc_dma, sc->sc_dma_physaddr);
- }
- #endif
- kfree(sc);
- return (-ENXIO);
- }
- /*
- * Detach an interface that successfully probed.
- */
- static void
- hipp_remove(struct pci_dev *dev)
- {
- struct hipp_softc *sc = pci_get_drvdata(dev);
- unsigned long l_flags;
- DPRINTF("%s()\n", __FUNCTION__);
- /* disable interrupts */
- HIPP_LOCK(sc);
- #if 0
- WRITE_REG_1(sc, HIFN_1_DMA_IER, 0);
- HIFN_UNLOCK(sc);
- /*XXX other resources */
- del_timer_sync(&sc->sc_tickto);
- /* Turn off DMA polling */
- WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
- HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
- #endif
- crypto_unregister_all(sc->sc_cid);
- free_irq(sc->sc_irq, sc);
- #if 0
- pci_free_consistent(sc->sc_pcidev, sizeof(*sc->sc_dma),
- sc->sc_dma, sc->sc_dma_physaddr);
- #endif
- }
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
- static irqreturn_t hipp_intr(int irq, void *arg)
- #else
- static irqreturn_t hipp_intr(int irq, void *arg, struct pt_regs *regs)
- #endif
- {
- struct hipp_softc *sc = arg;
- sc = sc; /* shut up compiler */
- return IRQ_HANDLED;
- }
- static struct pci_device_id hipp_pci_tbl[] = {
- { PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_7855,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
- { PCI_VENDOR_HIFN, PCI_PRODUCT_HIFN_8155,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
- { 0 }, /* terminating entry */
- };
- MODULE_DEVICE_TABLE(pci, hipp_pci_tbl);
- static struct pci_driver hipp_driver = {
- .name = "hipp",
- .id_table = hipp_pci_tbl,
- .probe = hipp_probe,
- .remove = hipp_remove,
- /* add PM stuff here one day */
- };
- static int __init hipp_init (void)
- {
- struct hipp_softc *sc = NULL;
- int rc;
- DPRINTF("%s(%p)\n", __FUNCTION__, hipp_init);
- rc = pci_register_driver(&hipp_driver);
- pci_register_driver_compat(&hipp_driver, rc);
- return rc;
- }
- static void __exit hipp_exit (void)
- {
- pci_unregister_driver(&hipp_driver);
- }
- module_init(hipp_init);
- module_exit(hipp_exit);
- MODULE_LICENSE("Dual BSD/GPL");
- MODULE_AUTHOR("Michael Richardson <mcr@xelerance.com>");
- MODULE_DESCRIPTION("OCF driver for hifn HIPP-I/II PCI crypto devices");
|