📄 ips.c
字号:
static inline void ips_putq_scb_tail(ips_scb_queue_t *, ips_scb_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 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 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 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_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 *);static int ips_erase_bios(ips_ha_t *);static int ips_program_bios(ips_ha_t *, char *, int);static int ips_verify_bios(ips_ha_t *, char *, int);static int ips_erase_bios_memio(ips_ha_t *);static int ips_program_bios_memio(ips_ha_t *, char *, int);static int ips_verify_bios_memio(ips_ha_t *, char *, int);#ifndef NO_IPS_CMDLINEstatic int ips_is_passthru(Scsi_Cmnd *);static int ips_make_passthru(ips_ha_t *, Scsi_Cmnd *, ips_scb_t *);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; char *p; char *key; char *value; char tokens[3] = {',', '.', 0}; 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}, }; METHOD_TRACE("ips_setup", 1); 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; } } }#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; u32 io_addr; u32 mem_addr; u32 io_len; u32 mem_len; u16 planer; u8 revision_id; u8 bus; u8 func; u8 irq; u16 deviceID[2]; int i; int j; 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) u32 currbar; u32 maskbar; u8 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 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_MORPHEUS_DEVICEID, morpheus); trombone = pci_find_device(IPS_VENDORID, IPS_COPPERHEAD_DEVICEID, trombone); /* determine which controller to probe first */ if (!morpheus) { /* we only have trombone */ dev[0] = trombone; dev[1] = NULL; deviceID[0] = IPS_COPPERHEAD_DEVICEID; } else if (!trombone) { /* we only have morpheus */ dev[0] = morpheus; dev[1] = NULL; deviceID[0] = IPS_MORPHEUS_DEVICEID; } else { /* we have both in the system */ if (trombone->bus < morpheus->bus) { dev[0] = trombone; dev[1] = morpheus; deviceID[0] = IPS_COPPERHEAD_DEVICEID; deviceID[1] = IPS_MORPHEUS_DEVICEID; } else if (trombone->bus > morpheus->bus) { dev[0] = morpheus; dev[1] = trombone; deviceID[0] = IPS_MORPHEUS_DEVICEID; deviceID[1] = IPS_COPPERHEAD_DEVICEID; } else { /* further detection required */ if (trombone->devfn < morpheus->devfn) { dev[0] = trombone; dev[1] = morpheus; deviceID[0] = IPS_COPPERHEAD_DEVICEID; deviceID[1] = IPS_MORPHEUS_DEVICEID; } else { dev[0] = morpheus; dev[1] = trombone; deviceID[0] = IPS_MORPHEUS_DEVICEID; deviceID[1] = IPS_COPPERHEAD_DEVICEID; } } } /* 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 { mem_addr = dev[i]->resource[j].start; mem_len = dev[i]->resource[j].end - dev[i]->resource[j].start + 1; }#else if (!dev[i]->base_address[j]) break; if ((dev[i]->base_address[j] & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { barnum = PCI_BASE_ADDRESS_0 + (j * 4); io_addr = dev[i]->base_address[j] & PCI_BASE_ADDRESS_IO_MASK; /* Get Size */ pci_read_config_dword(dev[i], barnum, &currbar); pci_write_config_dword(dev[i], barnum, ~0); pci_read_config_dword(dev[i], barnum, &maskbar); pci_write_config_dword(dev[i], barnum, currbar); io_len = ~(maskbar & PCI_BASE_ADDRESS_IO_MASK) + 1; } else { barnum = PCI_BASE_ADDRESS_0 + (j * 4); mem_addr = dev[i]->base_address[j] & PCI_BASE_ADDRESS_MEM_MASK; /* Get Size */ pci_read_config_dword(dev[i], barnum, &currbar); pci_write_config_dword(dev[i], barnum, ~0); pci_read_config_dword(dev[i], barnum, &maskbar); pci_write_config_dword(dev[i], barnum, currbar); mem_len = ~(maskbar & PCI_BASE_ADDRESS_MEM_MASK) + 1; }#endif } /* setup memory mapped area (if applicable) */ if (mem_addr) { u32 base; u32 offs; DEBUG_VAR(1, "(%s%d) detect, Memory region %x, size: %d", ips_name, ips_next_controller, mem_addr, mem_len);#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,17) if (check_mem_region(mem_addr, mem_len)) { /* Couldn't allocate io space */ printk(KERN_WARNING "(%s%d) couldn't allocate IO space %x len %d.\n", ips_name, ips_next_controller, io_addr, io_len); ips_next_controller++; continue; } request_mem_region(mem_addr, mem_len, "ips");#endif base = mem_addr & PAGE_MASK; offs = mem_addr - base; ioremap_ptr = ioremap(base, PAGE_SIZE); mem_ptr = ioremap_ptr + offs; } else { ioremap_ptr = NULL; mem_ptr = NULL; } /* setup I/O mapped area (if applicable) */ if (io_addr) { DEBUG_VAR(1, "(%s%d) detect, IO region %x, size: %d", ips_name, ips_next_controller, io_addr, io_len); if (check_region(io_addr, io_len)) { /* Couldn't allocate io space */ printk(KERN_WARNING "(%s%d) couldn't allocate IO space %x len %d.\n", ips_name, ips_next_controller, io_addr, io_len); ips_next_controller++; continue; } request_region(io_addr, io_len, "ips"); } /* get planer status */ if (pci_read_config_word(dev[i], 0x04, &planer)) { printk(KERN_WARNING "(%s%d) can't get planer status.\n", ips_name, ips_next_controller); ips_next_controller++; continue; } /* check to see if an onboard planer controller is disabled */ if (!(planer & 0x000C)) { DEBUG_VAR(1, "(%s%d) detect, Onboard ServeRAID disabled by BIOS", ips_name, ips_next_controller); ips_next_controller++; continue; } DEBUG_VAR(1, "(%s%d) detect bus %d, func %x, irq %d, io %x, mem: %x, ptr: %x", ips_name, ips_next_controller, bus, func, irq, io_addr, mem_addr, (u32) mem_ptr); /* get the revision ID */ if (pci_read_config_byte(dev[i], 0x08, &revision_id)) { printk(KERN_WARNING "(%s%d) can't get revision id.\n", ips_name, ips_next_controller);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -