📄 qla1280.c
字号:
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 ENTER("qla1280_detect");#ifdef CHECKSRBSIZE if (sizeof(srb_t) > sizeof(Scsi_Pointer) ) { printk("Redefine SRB - its too big"); return 0; }#endif#ifdef MODULE DEBUG(sprintf(debug_buff,"DEBUG: qla1280_detect starts at address = %p\n",qla1280_detect);) DEBUG(qla1280_print(debug_buff);) /* * If we are called as a module, the qla1280 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 * qla1280_setup * * Boot time Options * To add options at boot time add a line to your lilo.conf file like: * append="qla1280=verbose,max_tags:{{255,255,255,255},{255,255,255,255}}" * which will result in the first four devices on the first two * controllers being set to a tagged queue depth of 32. */ if(options) qla1280_setup(options, NULL); if(dummy_buffer[0] != 'P') printk(KERN_WARNING "qla1280: Please read the file /usr/src/linux/drivers" "/scsi/README.qla1280\n" "qla1280: to see the proper way to specify options to the qla1280 " "module\n" "qla1280: Specifically, don't use any commas when passing arguments to\n" "qla1280: 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]; qla1280_hostlist = NULL;#if 0 template->proc_dir = &proc_scsi_qla1280;#else template->proc_name = "qla1280";#endif /* 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(QLA1280_VENDOR_ID, bdp->device_id, pdev ) )) { if (pci_enable_device(pdev)) continue;#else while (!(pcibios_find_device(QLA1280_VENDOR_ID, bdp->device_id, index++, &pci_bus, &pci_devfn)) ) {#endif /* found a adapter */ host = scsi_register(template, sizeof(scsi_qla_host_t)); if (!host) { printk(KERN_WARNING "qla1280: Failed to register host, aborting.\n"); return 0; } scsi_set_pci_device(host, pdev); ha = (scsi_qla_host_t *) host->hostdata; /* Clear our data area */ for( j =0, cp = (char *)ha; j < sizeof(scsi_qla_host_t); j++) *cp = 0; /* Sanitize the information from PCI BIOS. */#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95) host->irq = pdev->irq; host->io_port = pci_resource_start(pdev, 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; host->io_port &= PCI_BASE_ADDRESS_IO_MASK; ha->pci_bus = pci_bus; ha->pci_device_fn = pci_devfn;#endif ha->device_id = bdp->device_id; ha->devnum = i; if( qla1280_mem_alloc(ha) ) { printk(KERN_INFO "qla1280: Failed to allocate memory for adapter\n"); } ha->ports = bdp->numPorts; ha->iobase = (device_reg_t *) host->io_port; ha->host = host; ha->host_no = host->host_no; /* load the F/W, read paramaters, and init the H/W */ if (qla1280_initialize_adapter(ha)) { printk(KERN_INFO "qla1280: Failed to initialized adapter\n"); qla1280_mem_free(ha); scsi_unregister(host); continue; } host->max_channel = bdp->numPorts-1; ha->instance = num_hosts; /* Register our resources with Linux */ if( qla1280_register_with_Linux(ha, bdp->numPorts-1) ) { printk(KERN_INFO "qla1280: Failed to register our resources\n"); qla1280_mem_free(ha); scsi_unregister(host); continue; } reg = ha->iobase; /* Disable ISP interrupts. */ qla1280_disable_intrs(ha); /* Insure mailbox registers are free. */ WRT_REG_WORD(®->semaphore, 0); WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); WRT_REG_WORD(®->host_cmd, HC_CLR_HOST_INT); /* Enable chip interrupts. */ qla1280_enable_intrs(ha); /* Insert new entry into the list of adapters */ ha->next = NULL; if( qla1280_hostlist == NULL ) { cur_ha = qla1280_hostlist = ha; } else { cur_ha = qla1280_hostlist; while( cur_ha->next != NULL ) cur_ha = cur_ha->next; cur_ha->next = ha; } num_hosts++; } /* end of WHILE */ } /* end of FOR */ LEAVE("qla1280_detect"); return num_hosts; }/*************************************************************************** qla1280_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 qla1280_register_with_Linux(scsi_qla_host_t *ha, uint8_t maxchannels){ struct Scsi_Host *host = ha->host; host->can_queue = 0xfffff; /* unlimited */ host->cmd_per_lun = 1; host->select_queue_depths = qla1280_select_queue_depth; host->n_io_port = 0xFF; host->base = (unsigned long) ha->mmpbase; host->max_channel = maxchannels; host->max_lun = MAX_LUNS-1; host->unique_id = ha->instance; host->max_id = MAX_TARGETS; host->unique_id = ha->instance; /* set our host ID (need to do something about our two IDs) */ host->this_id = ha->bus_settings[0].id; /* Register the IRQ with Linux (sharable) */ if ( request_irq(host->irq, qla1280_intr_handler, SA_INTERRUPT| SA_SHIRQ, "qla1280", ha)) { printk("qla1280 : Failed to reserved interrupt %d already in use\n", host->irq); qla1280_mem_free(ha); scsi_unregister(host); return 1; } /* Register the I/O space with Linux */ if (check_region(host->io_port, 0xff)) { printk("qla1280 : 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); qla1280_mem_free(ha); scsi_unregister(host); return 1; } request_region(host->io_port, 0xff, "qla1280"); return 0;}/************************************************************************** * qla1280_release * Free the passed in Scsi_Host memory structures prior to unloading the * module. **************************************************************************/intqla1280_release(struct Scsi_Host *host){ scsi_qla_host_t *ha = (scsi_qla_host_t *) host->hostdata; ENTER("qla1280_release"); if( !ha->flags.online ) return(0); /* turn-off interrupts on the card */ WRT_REG_WORD(&ha->iobase->ictrl, 0); /* Detach interrupts */ if(host->irq) free_irq(host->irq, ha); /* release io space registers */ if( host->io_port ) release_region(host->io_port, 0xff);#if MEMORY_MAPPED_IO if(ha->mmpbase) {#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) vfree((void *) (((unsigned long) ha->mmpbase) & PAGE_MASK));#else iounmap((void *) (((unsigned long) ha->mmpbase) & PAGE_MASK));#endif }#endif /* MEMORY_MAPPED_IO */ qla1280_mem_free(ha); ENTER("qla1280_release"); return(0);}/************************************************************************** * qla1280_info * Return a string describing the driver. **************************************************************************/const char *qla1280_info(struct Scsi_Host *host){ static char qla1280_buffer[125]; char *bp; scsi_qla_host_t *ha; qla_boards_t *bdp; bp = &qla1280_buffer[0]; ha = (scsi_qla_host_t *)host->hostdata; bdp = &QLBoardTbl[ha->devnum]; memset(bp, 0, sizeof(qla1280_buffer)); sprintf(bp, "QLogic %sPCI to SCSI Host Adapter: bus %d device %d irq %d\n" " Firmware version: %2d.%02d.%02d, Driver version %s", (char *)&bdp->bdName[0], ha->pci_bus, (ha->pci_device_fn & 0xf8) >> 3, host->irq, bdp->fwver[0],bdp->fwver[1],bdp->fwver[2], QLA1280_VERSION); return(bp);}/************************************************************************** * qla1200_queuecommand * Queue a command to the controller. * * Note: * The mid-level driver tries to ensures that queuecommand never gets invoked * concurrently with itself or the interrupt handler (although the * interrupt handler may call this routine as part of request-completion * handling). Unfortunely, it sometimes calls the scheduler in interrupt * context which is a big NO! NO!. **************************************************************************/intqla1280_queuecommand(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *)){ scsi_qla_host_t *ha; srb_t *sp;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) unsigned long cpu_flags = 0;#endif struct Scsi_Host *host; uint32_t b, t, l; scsi_lu_t *q; u_long handle; ENTER("qla1280_queuecommand"); COMTRACE('C') host = cmd->host; ha = (scsi_qla_host_t *) host->hostdata; /* send command to adapter */ sp = (srb_t *) CMD_SP(cmd); sp->cmd = cmd; cmd->scsi_done = fn; if (cmd->flags == 0) /* new command */ { sp->flags = 0; } DEBUG5(qla1280_print_scsi_cmd(cmd)); /* Generate LU queue on bus, target, LUN */ b = SCSI_BUS_32(cmd); t = SCSI_TCN_32(cmd); l = SCSI_LUN_32(cmd); if((q = LU_Q(ha, b, t, l)) == NULL ) { DRIVER_LOCK if( (q = (scsi_lu_t *)KMALLOC(sizeof(struct scsi_lu))) ) { LU_Q(ha, b, t, l) = q; BZERO(q,sizeof(struct scsi_lu)); DEBUG(sprintf(debug_buff,"Allocate new device queue 0x%x\n",q)); DEBUG(qla1280_print(debug_buff)); DRIVER_UNLOCK } else { CMD_RESULT(cmd) = (int) (DID_BUS_BUSY << 16); qla1280_done_q_put(sp, &ha->done_q_first, &ha->done_q_last); schedule_task(&ha->run_qla_bh); ha->flags.dpc_sched = TRUE; DRIVER_UNLOCK return(0); } } /* Set an invalid handle until we issue the command to ISP */ /* then we will set the real handle value. */ handle = INVALID_HANDLE; CMD_HANDLE(cmd) = (unsigned char *)handle;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -