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

📄 qla2x00.c

📁 QL2000卡的驱动程序,可以学习驱动的编程. 对于UNIX的I/O操作有帮助!
💻 C
📖 第 1 页 / 共 5 页
字号:
* qla2100_detect** Description:*    This routine will probe for Qlogic FC SCSI host adapters.*    It returns the number of host adapters of a particular*    type that were found.	 It also initialize all data necessary for*    the driver.  It is passed-in the host number, so that it*    knows where its first entry is in the scsi_hosts[] array.** Input:*     template - pointer to SCSI template** Returns:*  num - number of host adapters found.**************************************************************************/intqla2100_detect(Scsi_Host_Template *template) {    int num_hosts = 0;    struct Scsi_Host *host;    scsi_qla_host_t *ha, *cur_ha;    struct _qlaboards  *bdp;    int i, j;#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,1,95)    unsigned int piobase;    unsigned char pci_bus, pci_devfn, pci_irq;    config_reg_t   *cfgp = 0;#endif    device_reg_t   *reg;    char   *cp;#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)    struct pci_dev *pdev = NULL;#else    int index;#endif    struct semaphore sem = MUTEX_LOCKED;    unsigned long wait_switch = 0;     ENTER("qla2100_detect");#ifdef CODECHECK    if( sizeof(srb_t) > sizeof(Scsi_Pointer) ) {        printk("Redefine SRB - its too big");        return 0;    }#endif#ifdef MODULE    DEBUG2(sprintf(debug_buff,"DEBUG: qla2100_detect starts at address = 0x%8lx\n",(uint32_t)qla2100_detect);)    DEBUG2(qla2100_print(debug_buff);)    /*    * If we are called as a module, the qla2100 pointer may not be null    * and it would point to our bootup string, just like on the lilo    * command line.  IF not NULL, then process this config string with    * qla2100_setup    *    * Boot time Options    * To add options at boot time add a line to your lilo.conf file like:    * append="qla2100=verbose,tag_info:{{32,32,32,32},{32,32,32,32}}"    * which will result in the first four devices on the first two    * controllers being set to a tagged queue depth of 32.    */    if( ql2xopts )        qla2100_setup(ql2xopts, NULL);    if( dummy_buffer[0] != 'P' )        printk(KERN_WARNING "qla2100: Please read the file /usr/src/linux/drivers"        "/scsi/README.qla2100\n"        "qla2100: to see the proper way to specify options to the qla2100 "        "module\n"        "qla2100: Specifically, don't use any commas when passing arguments to\n"        "qla2100: insmod or else it might trash certain memory areas.\n");#endif    if( (int) !pcibios_present() ) {        printk("scsi: PCI not present\n");        return 0;    } /* end of IF */    bdp = &QLBoardTbl[0];    qla2100_hostlist = NULL;    template->proc_dir = &proc_scsi_qla2100;    /* Try and find each different type of adapter we support */    for( i=0; bdp->device_id != 0 && i < NUM_OF_ISP_DEVICES; i++, bdp++ ) {#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)        while( (pdev = pci_find_device(QLA2100_VENDOR_ID,        bdp->device_id, pdev) ) ) {            /* found a adapter */#else            while( !(pcibios_find_device(QLA2100_VENDOR_ID,            bdp->device_id,            index++, &pci_bus, &pci_devfn)) ) {                /* found a adapter */#endif                host = scsi_register(template, sizeof(scsi_qla_host_t));                ha = (scsi_qla_host_t *) host->hostdata;                /* Clear our data area */                /* tt 1/18/00 */                for( j =0, cp = (char *)ha;  j < sizeof(scsi_qla_host_t); j++, cp++ )                    *cp = 0;                /* Sanitize the information from PCI BIOS.  */#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)                host->irq = pdev->irq;                host->io_port = (unsigned int) pdev->base_address[0];                ha->pci_bus = pdev->bus->number;                ha->pci_device_fn = pdev->devfn;                ha->pdev = pdev;#else                pcibios_read_config_byte(pci_bus, pci_devfn, OFFSET(cfgp->interrupt_line), &pci_irq);                pcibios_read_config_dword(pci_bus, pci_devfn, OFFSET(cfgp->base_port), &piobase);                host->irq = pci_irq;                host->io_port = (unsigned int) piobase;                ha->pci_bus = pci_bus;                ha->pci_device_fn = pci_devfn;#endif                ha->device_id = bdp->device_id;                host->io_port &= PCI_BASE_ADDRESS_IO_MASK;                ha->devnum = i;                if( qla2100_verbose ) {                    printk("(scsi): Found a %s @ bus %d, device %d, irq %d, iobase 0x%x\n",                    bdp->bdName,ha->pci_bus, (ha->pci_device_fn & 0xf8) >> 3, host->irq,(int)host->io_port);                }                ha->iobase = (device_reg_t *) host->io_port;                ha->host = host;                if( qla2100_mem_alloc(ha) ) {                    printk(KERN_INFO "qla2100: Failed to allocate memory for adapter\n");                }                ha->prev_topology = 0;                ha->ports = bdp->numPorts;                ha->host_no = host->host_no;                if( ha->device_id == QLA2100_DEVICE_ID )                    ha->max_targets = MAX_TARGETS_2100;                else                    ha->max_targets = MAX_TARGETS_2200;                /* load the F/W, read paramaters, and init the H/W */                ha->instance = num_hosts;                if( qla2100_initialize_adapter(ha) ) {                    printk(KERN_INFO "qla2100: Failed to initialized adapter\n");                    qla2100_mem_free(ha);                    scsi_unregister(host);                    continue;                }                ha->next = NULL;                /*  Mark preallocated Loop IDs in use. */                ha->fabricid[SNS_FL_PORT].in_use = TRUE;                ha->fabricid[FABRIC_CONTROLLER].in_use = TRUE;                ha->fabricid[SIMPLE_NAME_SERVER].in_use = TRUE;                /* Register our resources with Linux */                if( qla2100_register_with_Linux(ha, bdp->numPorts-1) ) {                    printk(KERN_INFO "qla2100: Failed to register our resources\n");                    qla2100_mem_free(ha);                    scsi_unregister(host);                    continue;                }                reg = ha->iobase;                /* Disable ISP interrupts. */                qla2100_disable_intrs(ha);                /*                * Startup the kernel thread for this host adapter                */                ha->dpc_notify = &sem;                kernel_thread((int (*)(void *))qla2100_do_dpc,                (void *) ha, 0);                /*                * Now wait for the kernel dpc thread to initialize and go to sleep.                */                down(&sem);                ha->dpc_notify = NULL;                /*                * These locks are used to prevent more than one CPU from modifying the queue at                * the same time. The higher level "io_request_lock" will reduce most contention                * for these locks.                */                ha->retry_lock = SPIN_LOCK_UNLOCKED;                /* Insure mailbox registers are free. */                WRT_REG_WORD(&reg->semaphore, 0);                WRT_REG_WORD(&reg->host_cmd, HC_CLR_RISC_INT);                WRT_REG_WORD(&reg->host_cmd, HC_CLR_HOST_INT);		/* Wait around max 5 secs for the devices to come on-line */		/* we don't want Linux scanning before we are ready       */                 /* v2.19.5b6                                              */	        for (wait_switch = jiffies + (ha->loop_reset_delay * HZ);                         wait_switch > jiffies  &&                         !(ha->device_flags & DFLG_FABRIC_DEVICES) ;) {                     qla2100_check_fabric_devices(ha);                }                /* just in case we turned it on */	        ha->dpc_flags &= ~COMMAND_WAIT_NEEDED;                /* List the target we have found */                qla2100_display_fc_names(ha);                /* Enable chip interrupts. */                qla2100_enable_intrs(ha);                /* Insert new entry into the list of adapters */                ha->next = NULL;                if( qla2100_hostlist == NULL ) {                    qla2100_hostlist = ha;                } else {                    cur_ha = qla2100_hostlist;                    while( cur_ha->next != NULL )                        cur_ha = cur_ha->next;                    cur_ha->next = ha;                }                num_hosts++;            }        } /* end of FOR */        LEAVE("qla2100_detect");        return num_hosts;    }    /**************************************************************************    *   qla2100_register_with_Linux    *    * Description:    *   Free the passed in Scsi_Host memory structures prior to unloading the    *   module.    *    * Input:    *     ha - pointer to host adapter structure    *     maxchannels - MAX number of channels.    *    * Returns:    *  0 - Sucessfully reserved resources.    *  1 - Failed to reserved a resource.    **************************************************************************/    static uint8_t  qla2100_register_with_Linux(scsi_qla_host_t *ha, uint8_t maxchannels) {        struct Scsi_Host *host = ha->host;        char drvname[9];        host->can_queue = 0xfffff;  /* unlimited  */        host->cmd_per_lun = 1;        host->select_queue_depths = qla2100_select_queue_depth;        host->n_io_port = 0xFF;        host->base = (unsigned char *) ha->mmpbase;        host->max_channel = maxchannels;        /* fix: 07/31 host->max_lun = MAX_LUNS-1; */        host->max_lun = ha->max_luns;        host->unique_id = ha->instance;        host->max_id = ha->max_targets;        /* set our host ID  (need to do something about our two IDs) */        host->this_id = 255;        /* ER# 4368 */        sprintf(drvname,"qla2x00#%02d",host->unique_id);        /* Register the IRQ with Linux (sharable) */        if( request_irq(host->irq, qla2100_intr_handler, SA_INTERRUPT| SA_SHIRQ, "qla2x00", ha) ) {            printk("qla2100 : Failed to reserved interrupt %d already in use\n", host->irq);            return 1;        }        /* Register the I/O space with Linux */        if( check_region(host->io_port, 0xff) ) {            printk("qla2100 : Failed to reserved i/o region 0x%04lx-0x%04lx already in use\n",            host->io_port, host->io_port + 0xff);            free_irq(host->irq, NULL);            return 1;        }        request_region(host->io_port, 0xff, drvname);        /* Initialized the timer */        START_TIMER(qla2100_timer,ha,WATCH_INTERVAL);        return 0;    }    /**************************************************************************    *   qla2100_release    *    * Description:    *   Free the passed in Scsi_Host memory structures prior to unloading the    *   module.    *    * Input:    *     ha - pointer to host adapter structure    *    * Returns:    *  0 - Always returns good status    **************************************************************************/    int    qla2100_release(struct Scsi_Host *host) {        scsi_qla_host_t *ha = (scsi_qla_host_t *) host->hostdata;        ENTER("qla2100_release");        /* if adpater is running and online */        if( !ha->flags.online )            return(0);        /* turn-off interrupts on the card */        qla2100_disable_intrs(ha);        /* Detach interrupts */        if( host->irq )            free_irq(host->irq, ha);        /* release io space registers  */        if( host->io_port )            release_region(host->io_port, 0xff);        /* Disable timer */        if( ha->timer_active )            STOP_TIMER(qla2100_timer,ha)            /* Kill the kernel thread for this host */            if( ha->dpc_handler != NULL ) {                struct semaphore sem = MUTEX_LOCKED;                ha->dpc_notify = &sem;                send_sig(SIGKILL, ha->dpc_handler, 1);                down(&sem);                ha->dpc_notify = NULL;            }#if USE_FLASH            /* Move driver database to flash, if enabled. */            if( ha->flags.enable_flash_db_update && ha->flags.updated_fc_db ) {                ha->flags.updated_fc_db = FALSE;                qla2100_save_database(ha);            }#endif#if MEMORY_MAPPED_IO            if( ha->mmpbase ) {                iounmap((void *) (((unsigned long) ha->mmpbase) & PAGE_MASK));            }#endif /* MEMORY_MAPPED_IO */            qla2100_mem_free(ha);            ha->flags.online = FALSE;            LEAVE("qla2100_release");            return(0);    }    /**************************************************************************

⌨️ 快捷键说明

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