2  * This file is subject to the terms and conditions of the GNU General Public
 
   3  * License.  See the file "COPYING" in the main directory of this archive
 
   6  * Copyright (c) 2005 Silicon Graphics, Inc.  All rights reserved.
 
  10  *      MOATB Core Services driver.
 
  13 #include <linux/interrupt.h>
 
  14 #include <linux/module.h>
 
  15 #include <linux/moduleparam.h>
 
  16 #include <linux/types.h>
 
  17 #include <linux/ioport.h>
 
  18 #include <linux/notifier.h>
 
  19 #include <linux/reboot.h>
 
  20 #include <linux/init.h>
 
  22 #include <linux/delay.h>
 
  23 #include <linux/device.h>
 
  25 #include <linux/uio.h>
 
  26 #include <linux/mutex.h>
 
  28 #include <asm/uaccess.h>
 
  29 #include <asm/system.h>
 
  30 #include <asm/pgtable.h>
 
  31 #include <asm/sn/addrs.h>
 
  32 #include <asm/sn/intr.h>
 
  33 #include <asm/sn/tiocx.h>
 
  38 #define DBG(fmt...)    printk(KERN_ALERT fmt)
 
  42 static int mbcs_major;
 
  44 static LIST_HEAD(soft_list);
 
  49 static const struct file_operations mbcs_ops = {
 
  51         .llseek = mbcs_sram_llseek,
 
  52         .read = mbcs_sram_read,
 
  53         .write = mbcs_sram_write,
 
  54         .mmap = mbcs_gscr_mmap,
 
  57 struct mbcs_callback_arg {
 
  59         struct cx_dev *cx_dev;
 
  62 static inline void mbcs_getdma_init(struct getdma *gdma)
 
  64         memset(gdma, 0, sizeof(struct getdma));
 
  65         gdma->DoneIntEnable = 1;
 
  68 static inline void mbcs_putdma_init(struct putdma *pdma)
 
  70         memset(pdma, 0, sizeof(struct putdma));
 
  71         pdma->DoneIntEnable = 1;
 
  74 static inline void mbcs_algo_init(struct algoblock *algo_soft)
 
  76         memset(algo_soft, 0, sizeof(struct algoblock));
 
  79 static inline void mbcs_getdma_set(void *mmr,
 
  88                        uint64_t amoModType, uint64_t intrHostDest,
 
  91         union dma_control rdma_control;
 
  92         union dma_amo_dest amo_dest;
 
  93         union intr_dest intr_dest;
 
  94         union dma_localaddr local_addr;
 
  95         union dma_hostaddr host_addr;
 
  97         rdma_control.dma_control_reg = 0;
 
  98         amo_dest.dma_amo_dest_reg = 0;
 
  99         intr_dest.intr_dest_reg = 0;
 
 100         local_addr.dma_localaddr_reg = 0;
 
 101         host_addr.dma_hostaddr_reg = 0;
 
 103         host_addr.dma_sys_addr = hostAddr;
 
 104         MBCS_MMR_SET(mmr, MBCS_RD_DMA_SYS_ADDR, host_addr.dma_hostaddr_reg);
 
 106         local_addr.dma_ram_addr = localAddr;
 
 107         local_addr.dma_ram_sel = localRamSel;
 
 108         MBCS_MMR_SET(mmr, MBCS_RD_DMA_LOC_ADDR, local_addr.dma_localaddr_reg);
 
 110         rdma_control.dma_op_length = numPkts;
 
 111         rdma_control.done_amo_en = amoEnable;
 
 112         rdma_control.done_int_en = intrEnable;
 
 113         rdma_control.pio_mem_n = peerIO;
 
 114         MBCS_MMR_SET(mmr, MBCS_RD_DMA_CTRL, rdma_control.dma_control_reg);
 
 116         amo_dest.dma_amo_sys_addr = amoHostDest;
 
 117         amo_dest.dma_amo_mod_type = amoModType;
 
 118         MBCS_MMR_SET(mmr, MBCS_RD_DMA_AMO_DEST, amo_dest.dma_amo_dest_reg);
 
 120         intr_dest.address = intrHostDest;
 
 121         intr_dest.int_vector = intrVector;
 
 122         MBCS_MMR_SET(mmr, MBCS_RD_DMA_INT_DEST, intr_dest.intr_dest_reg);
 
 126 static inline void mbcs_putdma_set(void *mmr,
 
 129                        uint64_t localRamSel,
 
 134                        uint64_t amoHostDest,
 
 136                        uint64_t intrHostDest, uint64_t intrVector)
 
 138         union dma_control wdma_control;
 
 139         union dma_amo_dest amo_dest;
 
 140         union intr_dest intr_dest;
 
 141         union dma_localaddr local_addr;
 
 142         union dma_hostaddr host_addr;
 
 144         wdma_control.dma_control_reg = 0;
 
 145         amo_dest.dma_amo_dest_reg = 0;
 
 146         intr_dest.intr_dest_reg = 0;
 
 147         local_addr.dma_localaddr_reg = 0;
 
 148         host_addr.dma_hostaddr_reg = 0;
 
 150         host_addr.dma_sys_addr = hostAddr;
 
 151         MBCS_MMR_SET(mmr, MBCS_WR_DMA_SYS_ADDR, host_addr.dma_hostaddr_reg);
 
 153         local_addr.dma_ram_addr = localAddr;
 
 154         local_addr.dma_ram_sel = localRamSel;
 
 155         MBCS_MMR_SET(mmr, MBCS_WR_DMA_LOC_ADDR, local_addr.dma_localaddr_reg);
 
 157         wdma_control.dma_op_length = numPkts;
 
 158         wdma_control.done_amo_en = amoEnable;
 
 159         wdma_control.done_int_en = intrEnable;
 
 160         wdma_control.pio_mem_n = peerIO;
 
 161         MBCS_MMR_SET(mmr, MBCS_WR_DMA_CTRL, wdma_control.dma_control_reg);
 
 163         amo_dest.dma_amo_sys_addr = amoHostDest;
 
 164         amo_dest.dma_amo_mod_type = amoModType;
 
 165         MBCS_MMR_SET(mmr, MBCS_WR_DMA_AMO_DEST, amo_dest.dma_amo_dest_reg);
 
 167         intr_dest.address = intrHostDest;
 
 168         intr_dest.int_vector = intrVector;
 
 169         MBCS_MMR_SET(mmr, MBCS_WR_DMA_INT_DEST, intr_dest.intr_dest_reg);
 
 173 static inline void mbcs_algo_set(void *mmr,
 
 174                      uint64_t amoHostDest,
 
 176                      uint64_t intrHostDest,
 
 177                      uint64_t intrVector, uint64_t algoStepCount)
 
 179         union dma_amo_dest amo_dest;
 
 180         union intr_dest intr_dest;
 
 181         union algo_step step;
 
 183         step.algo_step_reg = 0;
 
 184         intr_dest.intr_dest_reg = 0;
 
 185         amo_dest.dma_amo_dest_reg = 0;
 
 187         amo_dest.dma_amo_sys_addr = amoHostDest;
 
 188         amo_dest.dma_amo_mod_type = amoModType;
 
 189         MBCS_MMR_SET(mmr, MBCS_ALG_AMO_DEST, amo_dest.dma_amo_dest_reg);
 
 191         intr_dest.address = intrHostDest;
 
 192         intr_dest.int_vector = intrVector;
 
 193         MBCS_MMR_SET(mmr, MBCS_ALG_INT_DEST, intr_dest.intr_dest_reg);
 
 195         step.alg_step_cnt = algoStepCount;
 
 196         MBCS_MMR_SET(mmr, MBCS_ALG_STEP, step.algo_step_reg);
 
 199 static inline int mbcs_getdma_start(struct mbcs_soft *soft)
 
 204         union cm_control cm_control;
 
 206         mmr_base = soft->mmr_base;
 
 207         gdma = &soft->getdma;
 
 209         /* check that host address got setup */
 
 214             (gdma->bytes + (MBCS_CACHELINE_SIZE - 1)) / MBCS_CACHELINE_SIZE;
 
 217         mbcs_getdma_set(mmr_base, tiocx_dma_addr(gdma->hostAddr),
 
 219                    (gdma->localAddr < MB2) ? 0 :
 
 220                    (gdma->localAddr < MB4) ? 1 :
 
 221                    (gdma->localAddr < MB6) ? 2 : 3,
 
 228                    gdma->intrHostDest, gdma->intrVector);
 
 231         cm_control.cm_control_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);
 
 232         cm_control.rd_dma_go = 1;
 
 233         MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, cm_control.cm_control_reg);
 
 239 static inline int mbcs_putdma_start(struct mbcs_soft *soft)
 
 244         union cm_control cm_control;
 
 246         mmr_base = soft->mmr_base;
 
 247         pdma = &soft->putdma;
 
 249         /* check that host address got setup */
 
 254             (pdma->bytes + (MBCS_CACHELINE_SIZE - 1)) / MBCS_CACHELINE_SIZE;
 
 257         mbcs_putdma_set(mmr_base, tiocx_dma_addr(pdma->hostAddr),
 
 259                    (pdma->localAddr < MB2) ? 0 :
 
 260                    (pdma->localAddr < MB4) ? 1 :
 
 261                    (pdma->localAddr < MB6) ? 2 : 3,
 
 268                    pdma->intrHostDest, pdma->intrVector);
 
 271         cm_control.cm_control_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);
 
 272         cm_control.wr_dma_go = 1;
 
 273         MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, cm_control.cm_control_reg);
 
 279 static inline int mbcs_algo_start(struct mbcs_soft *soft)
 
 281         struct algoblock *algo_soft = &soft->algo;
 
 282         void *mmr_base = soft->mmr_base;
 
 283         union cm_control cm_control;
 
 285         if (mutex_lock_interruptible(&soft->algolock))
 
 288         atomic_set(&soft->algo_done, 0);
 
 290         mbcs_algo_set(mmr_base,
 
 291                  algo_soft->amoHostDest,
 
 292                  algo_soft->amoModType,
 
 293                  algo_soft->intrHostDest,
 
 294                  algo_soft->intrVector, algo_soft->algoStepCount);
 
 296         /* start algorithm */
 
 297         cm_control.cm_control_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);
 
 298         cm_control.alg_done_int_en = 1;
 
 299         cm_control.alg_go = 1;
 
 300         MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, cm_control.cm_control_reg);
 
 302         mutex_unlock(&soft->algolock);
 
 307 static inline ssize_t
 
 308 do_mbcs_sram_dmawrite(struct mbcs_soft *soft, uint64_t hostAddr,
 
 309                       size_t len, loff_t * off)
 
 313         if (mutex_lock_interruptible(&soft->dmawritelock))
 
 316         atomic_set(&soft->dmawrite_done, 0);
 
 318         soft->putdma.hostAddr = hostAddr;
 
 319         soft->putdma.localAddr = *off;
 
 320         soft->putdma.bytes = len;
 
 322         if (mbcs_putdma_start(soft) < 0) {
 
 323                 DBG(KERN_ALERT "do_mbcs_sram_dmawrite: "
 
 324                                         "mbcs_putdma_start failed\n");
 
 329         if (wait_event_interruptible(soft->dmawrite_queue,
 
 330                                         atomic_read(&soft->dmawrite_done))) {
 
 339         mutex_unlock(&soft->dmawritelock);
 
 344 static inline ssize_t
 
 345 do_mbcs_sram_dmaread(struct mbcs_soft *soft, uint64_t hostAddr,
 
 346                      size_t len, loff_t * off)
 
 350         if (mutex_lock_interruptible(&soft->dmareadlock))
 
 353         atomic_set(&soft->dmawrite_done, 0);
 
 355         soft->getdma.hostAddr = hostAddr;
 
 356         soft->getdma.localAddr = *off;
 
 357         soft->getdma.bytes = len;
 
 359         if (mbcs_getdma_start(soft) < 0) {
 
 360                 DBG(KERN_ALERT "mbcs_strategy: mbcs_getdma_start failed\n");
 
 365         if (wait_event_interruptible(soft->dmaread_queue,
 
 366                                         atomic_read(&soft->dmaread_done))) {
 
 375         mutex_unlock(&soft->dmareadlock);
 
 380 static int mbcs_open(struct inode *ip, struct file *fp)
 
 382         struct mbcs_soft *soft;
 
 387         list_for_each_entry(soft, &soft_list, list) {
 
 388                 if (soft->nasid == minor) {
 
 389                         fp->private_data = soft->cxdev;
 
 397 static ssize_t mbcs_sram_read(struct file * fp, char __user *buf, size_t len, loff_t * off)
 
 399         struct cx_dev *cx_dev = fp->private_data;
 
 400         struct mbcs_soft *soft = cx_dev->soft;
 
 404         hostAddr = __get_dma_pages(GFP_KERNEL, get_order(len));
 
 408         rv = do_mbcs_sram_dmawrite(soft, hostAddr, len, off);
 
 412         if (copy_to_user(buf, (void *)hostAddr, len))
 
 416         free_pages(hostAddr, get_order(len));
 
 422 mbcs_sram_write(struct file * fp, const char __user *buf, size_t len, loff_t * off)
 
 424         struct cx_dev *cx_dev = fp->private_data;
 
 425         struct mbcs_soft *soft = cx_dev->soft;
 
 429         hostAddr = __get_dma_pages(GFP_KERNEL, get_order(len));
 
 433         if (copy_from_user((void *)hostAddr, buf, len)) {
 
 438         rv = do_mbcs_sram_dmaread(soft, hostAddr, len, off);
 
 441         free_pages(hostAddr, get_order(len));
 
 446 static loff_t mbcs_sram_llseek(struct file * filp, loff_t off, int whence)
 
 456                 newpos = filp->f_pos + off;
 
 460                 newpos = MBCS_SRAM_SIZE + off;
 
 463         default:                /* can't happen */
 
 470         filp->f_pos = newpos;
 
 475 static uint64_t mbcs_pioaddr(struct mbcs_soft *soft, uint64_t offset)
 
 479         mmr_base = (uint64_t) (soft->mmr_base + offset);
 
 484 static void mbcs_debug_pioaddr_set(struct mbcs_soft *soft)
 
 486         soft->debug_addr = mbcs_pioaddr(soft, MBCS_DEBUG_START);
 
 489 static void mbcs_gscr_pioaddr_set(struct mbcs_soft *soft)
 
 491         soft->gscr_addr = mbcs_pioaddr(soft, MBCS_GSCR_START);
 
 494 static int mbcs_gscr_mmap(struct file *fp, struct vm_area_struct *vma)
 
 496         struct cx_dev *cx_dev = fp->private_data;
 
 497         struct mbcs_soft *soft = cx_dev->soft;
 
 499         if (vma->vm_pgoff != 0)
 
 502         vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 
 504         /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */
 
 505         if (remap_pfn_range(vma,
 
 507                             __pa(soft->gscr_addr) >> PAGE_SHIFT,
 
 516  * mbcs_completion_intr_handler - Primary completion handler.
 
 518  * @arg: soft struct for device
 
 522 mbcs_completion_intr_handler(int irq, void *arg)
 
 524         struct mbcs_soft *soft = (struct mbcs_soft *)arg;
 
 526         union cm_status cm_status;
 
 527         union cm_control cm_control;
 
 529         mmr_base = soft->mmr_base;
 
 530         cm_status.cm_status_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_STATUS);
 
 532         if (cm_status.rd_dma_done) {
 
 533                 /* stop dma-read engine, clear status */
 
 534                 cm_control.cm_control_reg =
 
 535                     MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);
 
 536                 cm_control.rd_dma_clr = 1;
 
 537                 MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL,
 
 538                              cm_control.cm_control_reg);
 
 539                 atomic_set(&soft->dmaread_done, 1);
 
 540                 wake_up(&soft->dmaread_queue);
 
 542         if (cm_status.wr_dma_done) {
 
 543                 /* stop dma-write engine, clear status */
 
 544                 cm_control.cm_control_reg =
 
 545                     MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);
 
 546                 cm_control.wr_dma_clr = 1;
 
 547                 MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL,
 
 548                              cm_control.cm_control_reg);
 
 549                 atomic_set(&soft->dmawrite_done, 1);
 
 550                 wake_up(&soft->dmawrite_queue);
 
 552         if (cm_status.alg_done) {
 
 554                 cm_control.cm_control_reg =
 
 555                     MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);
 
 556                 cm_control.alg_done_clr = 1;
 
 557                 MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL,
 
 558                              cm_control.cm_control_reg);
 
 559                 atomic_set(&soft->algo_done, 1);
 
 560                 wake_up(&soft->algo_queue);
 
 567  * mbcs_intr_alloc - Allocate interrupts.
 
 568  * @dev: device pointer
 
 571 static int mbcs_intr_alloc(struct cx_dev *dev)
 
 573         struct sn_irq_info *sn_irq;
 
 574         struct mbcs_soft *soft;
 
 575         struct getdma *getdma;
 
 576         struct putdma *putdma;
 
 577         struct algoblock *algo;
 
 580         getdma = &soft->getdma;
 
 581         putdma = &soft->putdma;
 
 584         soft->get_sn_irq = NULL;
 
 585         soft->put_sn_irq = NULL;
 
 586         soft->algo_sn_irq = NULL;
 
 588         sn_irq = tiocx_irq_alloc(dev->cx_id.nasid, TIOCX_CORELET, -1, -1, -1);
 
 591         soft->get_sn_irq = sn_irq;
 
 592         getdma->intrHostDest = sn_irq->irq_xtalkaddr;
 
 593         getdma->intrVector = sn_irq->irq_irq;
 
 594         if (request_irq(sn_irq->irq_irq,
 
 595                         (void *)mbcs_completion_intr_handler, IRQF_SHARED,
 
 596                         "MBCS get intr", (void *)soft)) {
 
 597                 tiocx_irq_free(soft->get_sn_irq);
 
 601         sn_irq = tiocx_irq_alloc(dev->cx_id.nasid, TIOCX_CORELET, -1, -1, -1);
 
 602         if (sn_irq == NULL) {
 
 603                 free_irq(soft->get_sn_irq->irq_irq, soft);
 
 604                 tiocx_irq_free(soft->get_sn_irq);
 
 607         soft->put_sn_irq = sn_irq;
 
 608         putdma->intrHostDest = sn_irq->irq_xtalkaddr;
 
 609         putdma->intrVector = sn_irq->irq_irq;
 
 610         if (request_irq(sn_irq->irq_irq,
 
 611                         (void *)mbcs_completion_intr_handler, IRQF_SHARED,
 
 612                         "MBCS put intr", (void *)soft)) {
 
 613                 tiocx_irq_free(soft->put_sn_irq);
 
 614                 free_irq(soft->get_sn_irq->irq_irq, soft);
 
 615                 tiocx_irq_free(soft->get_sn_irq);
 
 619         sn_irq = tiocx_irq_alloc(dev->cx_id.nasid, TIOCX_CORELET, -1, -1, -1);
 
 620         if (sn_irq == NULL) {
 
 621                 free_irq(soft->put_sn_irq->irq_irq, soft);
 
 622                 tiocx_irq_free(soft->put_sn_irq);
 
 623                 free_irq(soft->get_sn_irq->irq_irq, soft);
 
 624                 tiocx_irq_free(soft->get_sn_irq);
 
 627         soft->algo_sn_irq = sn_irq;
 
 628         algo->intrHostDest = sn_irq->irq_xtalkaddr;
 
 629         algo->intrVector = sn_irq->irq_irq;
 
 630         if (request_irq(sn_irq->irq_irq,
 
 631                         (void *)mbcs_completion_intr_handler, IRQF_SHARED,
 
 632                         "MBCS algo intr", (void *)soft)) {
 
 633                 tiocx_irq_free(soft->algo_sn_irq);
 
 634                 free_irq(soft->put_sn_irq->irq_irq, soft);
 
 635                 tiocx_irq_free(soft->put_sn_irq);
 
 636                 free_irq(soft->get_sn_irq->irq_irq, soft);
 
 637                 tiocx_irq_free(soft->get_sn_irq);
 
 645  * mbcs_intr_dealloc - Remove interrupts.
 
 646  * @dev: device pointer
 
 649 static void mbcs_intr_dealloc(struct cx_dev *dev)
 
 651         struct mbcs_soft *soft;
 
 655         free_irq(soft->get_sn_irq->irq_irq, soft);
 
 656         tiocx_irq_free(soft->get_sn_irq);
 
 657         free_irq(soft->put_sn_irq->irq_irq, soft);
 
 658         tiocx_irq_free(soft->put_sn_irq);
 
 659         free_irq(soft->algo_sn_irq->irq_irq, soft);
 
 660         tiocx_irq_free(soft->algo_sn_irq);
 
 663 static inline int mbcs_hw_init(struct mbcs_soft *soft)
 
 665         void *mmr_base = soft->mmr_base;
 
 666         union cm_control cm_control;
 
 667         union cm_req_timeout cm_req_timeout;
 
 670         cm_req_timeout.cm_req_timeout_reg =
 
 671             MBCS_MMR_GET(mmr_base, MBCS_CM_REQ_TOUT);
 
 673         cm_req_timeout.time_out = MBCS_CM_CONTROL_REQ_TOUT_MASK;
 
 674         MBCS_MMR_SET(mmr_base, MBCS_CM_REQ_TOUT,
 
 675                      cm_req_timeout.cm_req_timeout_reg);
 
 677         mbcs_gscr_pioaddr_set(soft);
 
 678         mbcs_debug_pioaddr_set(soft);
 
 681         err_stat = MBCS_MMR_GET(mmr_base, MBCS_CM_ERR_STAT);
 
 682         MBCS_MMR_SET(mmr_base, MBCS_CM_CLR_ERR_STAT, err_stat);
 
 683         MBCS_MMR_ZERO(mmr_base, MBCS_CM_ERROR_DETAIL1);
 
 685         /* enable interrupts */
 
 686         /* turn off 2^23 (INT_EN_PIO_REQ_ADDR_INV) */
 
 687         MBCS_MMR_SET(mmr_base, MBCS_CM_ERR_INT_EN, 0x3ffffff7e00ffUL);
 
 689         /* arm status regs and clear engines */
 
 690         cm_control.cm_control_reg = MBCS_MMR_GET(mmr_base, MBCS_CM_CONTROL);
 
 691         cm_control.rearm_stat_regs = 1;
 
 692         cm_control.alg_clr = 1;
 
 693         cm_control.wr_dma_clr = 1;
 
 694         cm_control.rd_dma_clr = 1;
 
 696         MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, cm_control.cm_control_reg);
 
 701 static ssize_t show_algo(struct device *dev, struct device_attribute *attr, char *buf)
 
 703         struct cx_dev *cx_dev = to_cx_dev(dev);
 
 704         struct mbcs_soft *soft = cx_dev->soft;
 
 708          * By convention, the first debug register contains the
 
 709          * algorithm number and revision.
 
 711         debug0 = *(uint64_t *) soft->debug_addr;
 
 713         return sprintf(buf, "0x%lx 0x%lx\n",
 
 714                        (debug0 >> 32), (debug0 & 0xffffffff));
 
 717 static ssize_t store_algo(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 
 720         struct cx_dev *cx_dev = to_cx_dev(dev);
 
 721         struct mbcs_soft *soft = cx_dev->soft;
 
 726         n = simple_strtoul(buf, NULL, 0);
 
 729                 mbcs_algo_start(soft);
 
 730                 if (wait_event_interruptible(soft->algo_queue,
 
 731                                         atomic_read(&soft->algo_done)))
 
 738 DEVICE_ATTR(algo, 0644, show_algo, store_algo);
 
 741  * mbcs_probe - Initialize for device
 
 742  * @dev: device pointer
 
 743  * @device_id: id table pointer
 
 746 static int mbcs_probe(struct cx_dev *dev, const struct cx_device_id *id)
 
 748         struct mbcs_soft *soft;
 
 752         soft = kzalloc(sizeof(struct mbcs_soft), GFP_KERNEL);
 
 756         soft->nasid = dev->cx_id.nasid;
 
 757         list_add(&soft->list, &soft_list);
 
 758         soft->mmr_base = (void *)tiocx_swin_base(dev->cx_id.nasid);
 
 762         init_waitqueue_head(&soft->dmawrite_queue);
 
 763         init_waitqueue_head(&soft->dmaread_queue);
 
 764         init_waitqueue_head(&soft->algo_queue);
 
 766         mutex_init(&soft->dmawritelock);
 
 767         mutex_init(&soft->dmareadlock);
 
 768         mutex_init(&soft->algolock);
 
 770         mbcs_getdma_init(&soft->getdma);
 
 771         mbcs_putdma_init(&soft->putdma);
 
 772         mbcs_algo_init(&soft->algo);
 
 776         /* Allocate interrupts */
 
 777         mbcs_intr_alloc(dev);
 
 779         device_create_file(&dev->dev, &dev_attr_algo);
 
 784 static int mbcs_remove(struct cx_dev *dev)
 
 787                 mbcs_intr_dealloc(dev);
 
 791         device_remove_file(&dev->dev, &dev_attr_algo);
 
 796 static const struct cx_device_id __devinitdata mbcs_id_table[] = {
 
 798          .part_num = MBCS_PART_NUM,
 
 799          .mfg_num = MBCS_MFG_NUM,
 
 802          .part_num = MBCS_PART_NUM_ALG0,
 
 803          .mfg_num = MBCS_MFG_NUM,
 
 808 MODULE_DEVICE_TABLE(cx, mbcs_id_table);
 
 810 static struct cx_drv mbcs_driver = {
 
 812         .id_table = mbcs_id_table,
 
 814         .remove = mbcs_remove,
 
 817 static void __exit mbcs_exit(void)
 
 819         unregister_chrdev(mbcs_major, DEVICE_NAME);
 
 820         cx_driver_unregister(&mbcs_driver);
 
 823 static int __init mbcs_init(void)
 
 827         if (!ia64_platform_is("sn2"))
 
 830         // Put driver into chrdevs[].  Get major number.
 
 831         rv = register_chrdev(mbcs_major, DEVICE_NAME, &mbcs_ops);
 
 833                 DBG(KERN_ALERT "mbcs_init: can't get major number. %d\n", rv);
 
 838         return cx_driver_register(&mbcs_driver);
 
 841 module_init(mbcs_init);
 
 842 module_exit(mbcs_exit);
 
 844 MODULE_AUTHOR("Bruce Losure <blosure@sgi.com>");
 
 845 MODULE_DESCRIPTION("Driver for MOATB Core Services");
 
 846 MODULE_LICENSE("GPL");