?? ips.c
字號:
static int ips_reqsen(ips_ha_t *, ips_scb_t *);static int ips_allocatescbs(ips_ha_t *);static int ips_reset_copperhead(ips_ha_t *);static int ips_reset_copperhead_memio(ips_ha_t *);static int ips_reset_morpheus(ips_ha_t *);static int ips_issue_copperhead(ips_ha_t *, ips_scb_t *);static int ips_issue_copperhead_memio(ips_ha_t *, ips_scb_t *);static int ips_issue_i2o(ips_ha_t *, ips_scb_t *);static int ips_issue_i2o_memio(ips_ha_t *, ips_scb_t *);static int ips_isintr_copperhead(ips_ha_t *);static int ips_isintr_copperhead_memio(ips_ha_t *);static int ips_isintr_morpheus(ips_ha_t *);static int ips_wait(ips_ha_t *, int, int);static int ips_write_driver_status(ips_ha_t *, int);static int ips_read_adapter_status(ips_ha_t *, int);static int ips_read_subsystem_parameters(ips_ha_t *, int);static int ips_read_config(ips_ha_t *, int);static int ips_clear_adapter(ips_ha_t *, int);static int ips_readwrite_page5(ips_ha_t *, int, int);static int ips_init_copperhead(ips_ha_t *);static int ips_init_copperhead_memio(ips_ha_t *);static int ips_init_morpheus(ips_ha_t *);static int ips_isinit_copperhead(ips_ha_t *);static int ips_isinit_copperhead_memio(ips_ha_t *);static int ips_isinit_morpheus(ips_ha_t *);static int ips_erase_bios(ips_ha_t *);static int ips_program_bios(ips_ha_t *, char *, u_int32_t, u_int32_t);static int ips_verify_bios(ips_ha_t *, char *, u_int32_t, u_int32_t);static int ips_erase_bios_memio(ips_ha_t *);static int ips_program_bios_memio(ips_ha_t *, char *, u_int32_t, u_int32_t);static int ips_verify_bios_memio(ips_ha_t *, char *, u_int32_t, u_int32_t);static void ips_flash_bios_section(void *);static void ips_flash_bios_segment(void *);static void ips_scheduled_flash_bios(void *);static void ips_create_nvrampage5(ips_ha_t *, IPS_NVRAM_P5 *);static void ips_get_bios_version(ips_ha_t *, int);static void ips_identify_controller(ips_ha_t *);static void ips_select_queue_depth(struct Scsi_Host *, Scsi_Device *);static void ips_chkstatus(ips_ha_t *, IPS_STATUS *);static void ips_enable_int_copperhead(ips_ha_t *);static void ips_enable_int_copperhead_memio(ips_ha_t *);static void ips_enable_int_morpheus(ips_ha_t *);static void ips_intr_copperhead(ips_ha_t *);static void ips_intr_morpheus(ips_ha_t *);static void ips_next(ips_ha_t *, int);static void ipsintr_blocking(ips_ha_t *, struct ips_scb *);static void ipsintr_done(ips_ha_t *, struct ips_scb *);static void ips_done(ips_ha_t *, ips_scb_t *);static void ips_free(ips_ha_t *);static void ips_init_scb(ips_ha_t *, ips_scb_t *);static void ips_freescb(ips_ha_t *, ips_scb_t *);static void ips_statinit(ips_ha_t *);static void ips_statinit_memio(ips_ha_t *);static void ips_fix_ffdc_time(ips_ha_t *, ips_scb_t *, time_t);static void ips_ffdc_reset(ips_ha_t *, int);static void ips_ffdc_time(ips_ha_t *, int);static u_int32_t ips_statupd_copperhead(ips_ha_t *);static u_int32_t ips_statupd_copperhead_memio(ips_ha_t *);static u_int32_t ips_statupd_morpheus(ips_ha_t *);static ips_scb_t * ips_getscb(ips_ha_t *);static inline void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *);static inline void ips_putq_scb_tail(ips_scb_queue_t *, ips_scb_t *);static inline void ips_putq_wait_head(ips_wait_queue_t *, Scsi_Cmnd *);static inline void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *);static inline void ips_putq_copp_head(ips_copp_queue_t *, ips_copp_wait_item_t *);static inline void ips_putq_copp_tail(ips_copp_queue_t *, ips_copp_wait_item_t *);static inline ips_scb_t * ips_removeq_scb_head(ips_scb_queue_t *);static inline ips_scb_t * ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *);static inline Scsi_Cmnd * ips_removeq_wait_head(ips_wait_queue_t *);static inline Scsi_Cmnd * ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *);static inline ips_copp_wait_item_t * ips_removeq_copp(ips_copp_queue_t *, ips_copp_wait_item_t *);static inline ips_copp_wait_item_t * ips_removeq_copp_head(ips_copp_queue_t *);#ifndef NO_IPS_CMDLINEstatic int ips_is_passthru(Scsi_Cmnd *);static int ips_make_passthru(ips_ha_t *, Scsi_Cmnd *, ips_scb_t *, int);static int ips_usrcmd(ips_ha_t *, ips_passthru_t *, ips_scb_t *);static int ips_newusrcmd(ips_ha_t *, ips_passthru_t *, ips_scb_t *);static void ips_cleanup_passthru(ips_ha_t *, ips_scb_t *);#endifint ips_proc_info(char *, char **, off_t, int, int, int);static int ips_host_info(ips_ha_t *, char *, off_t, int);static void copy_mem_info(IPS_INFOSTR *, char *, int);static int copy_info(IPS_INFOSTR *, char *, ...);/*--------------------------------------------------------------------------*//* Exported Functions *//*--------------------------------------------------------------------------*//****************************************************************************//* *//* Routine Name: ips_setup *//* *//* Routine Description: *//* *//* setup parameters to the driver *//* *//****************************************************************************/#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,13)static intips_setup(char *ips_str) {#elsevoidips_setup(char *ips_str, int *dummy) {#endif int i;#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,0) char *p; char tokens[3] = {',', '.', 0};#endif char *key; char *value; IPS_OPTION options[] = { {"noreset", &ips_resetcontroller, 0},#ifdef IPS_DEBUG {"debug", &ips_debug, 1},#endif {"noi2o", &ips_force_i2o, 0}, {"nommap", &ips_force_memio, 0}, {"nocmdline", &ips_cmdline, 0}, {"ioctlsize", &ips_ioctlsize, IPS_IOCTL_SIZE}, {"cdboot", &ips_cd_boot, 0}, }; METHOD_TRACE("ips_setup", 1);/* Don't use strtok() anymore ( if 2.4 Kernel or beyond ) */#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) /* Search for value */ while ((key = strsep(&ips_str, ",."))) { if (!*key) continue; value = strchr(key, ':'); if (value) *value++ = '\0'; /* * We now have key/value pairs. * Update the variables */ for (i = 0; i < (sizeof(options) / sizeof(options[0])); i++) { if (strnicmp(key, options[i].option_name, strlen(options[i].option_name)) == 0) { if (value) *options[i].option_flag = simple_strtoul(value, NULL, 0); else *options[i].option_flag = options[i].option_value; break; } } }#else for (key = strtok(ips_str, tokens); key; key = strtok(NULL, tokens)) { p = key; /* Search for value */ while ((p) && (*p != ':')) p++; if (p) { *p = '\0'; value = p+1; } else value = NULL; /* * We now have key/value pairs. * Update the variables */ for (i = 0; i < (sizeof(options) / sizeof(options[0])); i++) { if (strnicmp(key, options[i].option_name, strlen(ips_str)) == 0) { if (value) *options[i].option_flag = simple_strtoul(value, NULL, 0); else *options[i].option_flag = options[i].option_value; break; } } }#endif#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,13) return (1);#endif}#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,13)__setup("ips=", ips_setup);#endif/****************************************************************************//* *//* Routine Name: ips_detect *//* *//* Routine Description: *//* *//* Detect and initialize the driver *//* *//* NOTE: this routine is called under the io_request_lock spinlock *//* *//****************************************************************************/intips_detect(Scsi_Host_Template *SHT) { struct Scsi_Host *sh; ips_ha_t *ha; u_int32_t io_addr; u_int32_t mem_addr; u_int32_t io_len; u_int32_t mem_len; u_int16_t planer; u_int8_t revision_id; u_int8_t bus; u_int8_t func; u_int8_t irq; u_int16_t deviceID[2]; u_int16_t subdevice_id; int i; int j; u_int32_t count; char *ioremap_ptr; char *mem_ptr; struct pci_dev *dev[2]; struct pci_dev *morpheus = NULL; struct pci_dev *trombone = NULL;#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,14) u_int32_t currbar; u_int32_t maskbar; u_int8_t barnum;#endif METHOD_TRACE("ips_detect", 1);#ifdef MODULE if (ips)#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,13) ips_setup(ips);#else ips_setup(ips, NULL);#endif#endif /* If Booting from the ServeRAID Manager CD, Allocate a large Flash */ /* Buffer ( so we won't need to allocate one for each adapter ). */ if ( ips_cd_boot ) { ips_FlashData = ( char * ) __get_free_pages( GFP_KERNEL, 7 ); if (ips_FlashData == NULL) { /* The validity of this pointer is checked in ips_make_passthru() before it is used */ printk( KERN_WARNING "ERROR: Can't Allocate Large Buffer for Flashing\n" ); } } SHT->proc_info = ips_proc_info;#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27) SHT->proc_dir = &proc_scsi_ips;#else SHT->proc_name = "ips";#endif#if defined(CONFIG_PCI) /* initalize number of controllers */ ips_num_controllers = 0; ips_next_controller = 0; ips_released_controllers = 0; if (!pci_present()) return (0); morpheus = pci_find_device(IPS_VENDORID, IPS_DEVICEID_MORPHEUS, morpheus); trombone = pci_find_device(IPS_VENDORID, IPS_DEVICEID_COPPERHEAD, trombone); /* determine which controller to probe first */ if (!morpheus) { /* we only have trombone */ dev[0] = trombone; dev[1] = NULL; deviceID[0] = IPS_DEVICEID_COPPERHEAD; } else if (!trombone) { /* we only have morpheus */ dev[0] = morpheus; dev[1] = NULL; deviceID[0] = IPS_DEVICEID_MORPHEUS; } else { /* we have both in the system */ if (trombone->bus->number < morpheus->bus->number) { dev[0] = trombone; dev[1] = morpheus; deviceID[0] = IPS_DEVICEID_COPPERHEAD; deviceID[1] = IPS_DEVICEID_MORPHEUS; } else if (trombone->bus->number > morpheus->bus->number) { dev[0] = morpheus; dev[1] = trombone; deviceID[0] = IPS_DEVICEID_MORPHEUS; deviceID[1] = IPS_DEVICEID_COPPERHEAD; } else { /* further detection required */ if (trombone->devfn < morpheus->devfn) { dev[0] = trombone; dev[1] = morpheus; deviceID[0] = IPS_DEVICEID_COPPERHEAD; deviceID[1] = IPS_DEVICEID_MORPHEUS; } else { dev[0] = morpheus; dev[1] = trombone; deviceID[0] = IPS_DEVICEID_MORPHEUS; deviceID[1] = IPS_DEVICEID_COPPERHEAD; } } } /* Now scan the controllers */ for (i = 0; i < 2; i++) { if (!dev[i]) break; do { if (ips_next_controller >= IPS_MAX_ADAPTERS) break;#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) if (pci_enable_device(dev[i])) break;#endif /* stuff that we get in dev */ irq = dev[i]->irq; bus = dev[i]->bus->number; func = dev[i]->devfn; /* Init MEM/IO addresses to 0 */ mem_addr = 0; io_addr = 0; mem_len = 0; io_len = 0; for (j = 0; j < 2; j++) {#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) if (!pci_resource_start(dev[i], j)) break; if (pci_resource_flags(dev[i], j) & IORESOURCE_IO) { io_addr = pci_resource_start(dev[i], j); io_len = pci_resource_len(dev[i], j); } else { mem_addr = pci_resource_start(dev[i], j); mem_len = pci_resource_len(dev[i], j); }#elif LINUX_VERSION_CODE >= LinuxVersionCode(2,3,14) if (!dev[i]->resource[j].start) break; if ((dev[i]->resource[j].start & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { io_addr = dev[i]->resource[j].start; io_len = dev[i]->resource[j].end - dev[i]->resource[j].start + 1; } else {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -