qla_init.c
来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,528 行 · 第 1/5 页
C
2,528 行
/* Get host addresses. */ rval = qla2x00_get_adapter_id(ha, &loop_id, &al_pa, &area, &domain, &topo); if (rval != QLA_SUCCESS) { qla_printk(KERN_WARNING, ha, "ERROR -- Unable to get host loop ID.\n"); return (rval); } if (topo == 4) { qla_printk(KERN_INFO, ha, "Cannot get topology - retrying.\n"); return (QLA_FUNCTION_FAILED); } ha->loop_id = loop_id; /* initialize */ ha->min_external_loopid = SNS_FIRST_LOOP_ID; ha->operating_mode = LOOP; switch (topo) { case 0: DEBUG3(printk("scsi(%ld): HBA in NL topology.\n", ha->host_no)); ha->current_topology = ISP_CFG_NL; strcpy(connect_type, "(Loop)"); break; case 1: DEBUG3(printk("scsi(%ld): HBA in FL topology.\n", ha->host_no)); ha->current_topology = ISP_CFG_FL; strcpy(connect_type, "(FL_Port)"); break; case 2: DEBUG3(printk("scsi(%ld): HBA in N P2P topology.\n", ha->host_no)); ha->operating_mode = P2P; ha->current_topology = ISP_CFG_N; strcpy(connect_type, "(N_Port-to-N_Port)"); break; case 3: DEBUG3(printk("scsi(%ld): HBA in F P2P topology.\n", ha->host_no)); ha->operating_mode = P2P; ha->current_topology = ISP_CFG_F; strcpy(connect_type, "(F_Port)"); break; default: DEBUG3(printk("scsi(%ld): HBA in unknown topology %x. " "Using NL.\n", ha->host_no, topo)); ha->current_topology = ISP_CFG_NL; strcpy(connect_type, "(Loop)"); break; } /* Save Host port and loop ID. */ /* byte order - Big Endian */ ha->d_id.b.domain = domain; ha->d_id.b.area = area; ha->d_id.b.al_pa = al_pa; if (!ha->flags.init_done) qla_printk(KERN_INFO, ha, "Topology - %s, Host Loop address 0x%x\n", connect_type, ha->loop_id); if (rval) { DEBUG2_3(printk("scsi(%ld): FAILED.\n", ha->host_no)); } else { DEBUG3(printk("scsi(%ld): exiting normally.\n", ha->host_no)); } return(rval);}/** NVRAM configuration for ISP 2xxx** Input:* ha = adapter block pointer.** Output:* initialization control block in response_ring* host adapters parameters in host adapter block** Returns:* 0 = success.*/static intqla2x00_nvram_config(scsi_qla_host_t *ha){ int rval; uint8_t chksum = 0; uint16_t cnt; uint8_t *dptr1, *dptr2; init_cb_t *icb = ha->init_cb; nvram_t *nv = (nvram_t *)ha->request_ring; uint16_t *wptr = (uint16_t *)ha->request_ring; device_reg_t *reg = ha->iobase; uint8_t timer_mode; rval = QLA_SUCCESS; if (ha->flags.init_done) return (rval); /* Determine NVRAM starting address. */ ha->nvram_base = 0; if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) if ((RD_REG_WORD(®->ctrl_status) >> 14) == 1) ha->nvram_base = 0x80; /* Get NVRAM data and calculate checksum. */ qla2x00_lock_nvram_access(ha); for (cnt = 0; cnt < sizeof(nvram_t)/2; cnt++) { *wptr = cpu_to_le16(qla2x00_get_nvram_word(ha, (cnt+ha->nvram_base))); chksum += (uint8_t)*wptr; chksum += (uint8_t)(*wptr >> 8); wptr++; } qla2x00_unlock_nvram_access(ha); DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", ha->host_no)); DEBUG5(qla2x00_dump_buffer((uint8_t *)ha->request_ring, sizeof(nvram_t))); /* Bad NVRAM data, set defaults parameters. */ if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P' || nv->id[3] != ' ' || nv->nvram_version < 1) { /* Reset NVRAM data. */ qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: " "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0], nv->nvram_version); qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet " "invalid -- WWPN) defaults.\n"); /* * Set default initialization control block. */ memset(nv, 0, sizeof(nvram_t)); nv->parameter_block_version = ICB_VERSION; if (IS_QLA23XX(ha)) { nv->firmware_options[0] = BIT_2 | BIT_1; nv->firmware_options[1] = BIT_7 | BIT_5; nv->add_firmware_options[0] = BIT_5; nv->add_firmware_options[1] = BIT_5 | BIT_4; nv->frame_payload_size = __constant_cpu_to_le16(2048); nv->special_options[1] = BIT_7; } else if (IS_QLA2200(ha)) { nv->firmware_options[0] = BIT_2 | BIT_1; nv->firmware_options[1] = BIT_7 | BIT_5; nv->add_firmware_options[0] = BIT_5; nv->add_firmware_options[1] = BIT_5 | BIT_4; nv->frame_payload_size = __constant_cpu_to_le16(1024); } else if (IS_QLA2100(ha)) { nv->firmware_options[0] = BIT_3 | BIT_1; nv->firmware_options[1] = BIT_5; nv->frame_payload_size = __constant_cpu_to_le16(1024); } nv->max_iocb_allocation = __constant_cpu_to_le16(256); nv->execution_throttle = __constant_cpu_to_le16(16); nv->retry_count = 8; nv->retry_delay = 1; nv->port_name[0] = 33; nv->port_name[3] = 224; nv->port_name[4] = 139; nv->login_timeout = 4; /* * Set default host adapter parameters */ nv->host_p[1] = BIT_2; nv->reset_delay = 5; nv->port_down_retry_count = 8; nv->max_luns_per_target = __constant_cpu_to_le16(8); nv->link_down_timeout = 60; rval = 1; }#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) /* * The SN2 does not provide BIOS emulation which means you can't change * potentially bogus BIOS settings. Force the use of default settings * for link rate and frame size. Hope that the rest of the settings * are valid. */ if (ia64_platform_is("sn2")) { nv->frame_payload_size = __constant_cpu_to_le16(2048); if (IS_QLA23XX(ha)) nv->special_options[1] = BIT_7; }#endif /* Reset Initialization control block */ memset(icb, 0, sizeof(init_cb_t)); /* * Setup driver NVRAM options. */ nv->firmware_options[0] |= (BIT_6 | BIT_1); nv->firmware_options[0] &= ~(BIT_5 | BIT_4); nv->firmware_options[1] |= (BIT_5 | BIT_0); nv->firmware_options[1] &= ~BIT_4; if (IS_QLA23XX(ha)) { nv->firmware_options[0] |= BIT_2; nv->firmware_options[0] &= ~BIT_3; if (IS_QLA2300(ha)) { if (ha->fb_rev == FPM_2310) { strcpy(ha->model_number, "QLA2310"); } else { strcpy(ha->model_number, "QLA2300"); } } else { if (rval == 0 && memcmp(nv->model_number, BINZERO, sizeof(nv->model_number)) != 0) { char *st, *en; strncpy(ha->model_number, nv->model_number, sizeof(nv->model_number)); st = en = ha->model_number; en += sizeof(nv->model_number) - 1; while (en > st) { if (*en != 0x20 && *en != 0x00) break; *en-- = '\0'; } } else { uint16_t index; index = (ha->pdev->subsystem_device & 0xff); if (index < QLA_MODEL_NAMES) { strcpy(ha->model_number, qla2x00_model_name[index]); ha->model_desc = qla2x00_model_desc[index]; } else { strcpy(ha->model_number, "QLA23xx"); } } } } else if (IS_QLA2200(ha)) { nv->firmware_options[0] |= BIT_2; /* * 'Point-to-point preferred, else loop' is not a safe * connection mode setting. */ if ((nv->add_firmware_options[0] & (BIT_6 | BIT_5 | BIT_4)) == (BIT_5 | BIT_4)) { /* Force 'loop preferred, else point-to-point'. */ nv->add_firmware_options[0] &= ~(BIT_6 | BIT_5 | BIT_4); nv->add_firmware_options[0] |= BIT_5; } strcpy(ha->model_number, "QLA22xx"); } else /*if (IS_QLA2100(ha))*/ { strcpy(ha->model_number, "QLA2100"); } /* * Copy over NVRAM RISC parameter block to initialization control block. */ dptr1 = (uint8_t *)icb; dptr2 = (uint8_t *)&nv->parameter_block_version; cnt = (uint8_t *)&icb->request_q_outpointer - (uint8_t *)&icb->version; while (cnt--) *dptr1++ = *dptr2++; /* Copy 2nd half. */ dptr1 = (uint8_t *)icb->add_firmware_options; cnt = (uint8_t *)icb->reserved_3 - (uint8_t *)icb->add_firmware_options; while (cnt--) *dptr1++ = *dptr2++; /* Prepare nodename */ if ((icb->firmware_options[1] & BIT_6) == 0) { /* * Firmware will apply the following mask if the nodename was * not provided. */ memcpy(icb->node_name, icb->port_name, WWN_SIZE); icb->node_name[0] &= 0xF0; } /* * Set host adapter parameters. */ ha->nvram_version = nv->nvram_version; ha->flags.disable_risc_code_load = ((nv->host_p[0] & BIT_4) ? 1 : 0); /* Always load RISC code on non ISP2[12]00 chips. */ if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) ha->flags.disable_risc_code_load = 0; ha->flags.enable_lip_reset = ((nv->host_p[1] & BIT_1) ? 1 : 0); ha->flags.enable_lip_full_login = ((nv->host_p[1] & BIT_2) ? 1 : 0); ha->flags.enable_target_reset = ((nv->host_p[1] & BIT_3) ? 1 : 0); ha->operating_mode = (icb->add_firmware_options[0] & (BIT_6 | BIT_5 | BIT_4)) >> 4; ha->fw_seriallink_options[0] = nv->seriallink_options[0]; ha->fw_seriallink_options[1] = nv->seriallink_options[1]; /* save HBA serial number */ ha->serial0 = icb->port_name[5]; ha->serial1 = icb->port_name[6]; ha->serial2 = icb->port_name[7]; memcpy(ha->node_name, icb->node_name, WWN_SIZE); icb->execution_throttle = __constant_cpu_to_le16(0xFFFF); ha->retry_count = nv->retry_count; /* Set minimum login_timeout to 4 seconds. */ if (nv->login_timeout < ql2xlogintimeout) nv->login_timeout = ql2xlogintimeout; if (nv->login_timeout < 4) nv->login_timeout = 4; ha->login_timeout = nv->login_timeout; icb->login_timeout = nv->login_timeout; /* Set minimum RATOV to 200 tenths of a second. */ ha->r_a_tov = 200; ha->minimum_timeout = (ha->login_timeout * ha->retry_count) + nv->port_down_retry_count; ha->loop_reset_delay = nv->reset_delay; /* Will get the value from NVRAM. */ ha->loop_down_timeout = LOOP_DOWN_TIMEOUT; /* Link Down Timeout = 0: * * When Port Down timer expires we will start returning * I/O's to OS with "DID_NO_CONNECT". * * Link Down Timeout != 0: * * The driver waits for the link to come up after link down * before returning I/Os to OS with "DID_NO_CONNECT". */ if (nv->link_down_timeout == 0) { ha->loop_down_abort_time = (LOOP_DOWN_TIME - ha->loop_down_timeout); } else { ha->link_down_timeout = nv->link_down_timeout; ha->loop_down_abort_time = (LOOP_DOWN_TIME - ha->link_down_timeout); } ha->max_luns = MAX_LUNS; ha->max_probe_luns = le16_to_cpu(nv->max_luns_per_target); if (ha->max_probe_luns == 0) ha->max_probe_luns = MIN_LUNS; /* * Need enough time to try and get the port back. */ ha->port_down_retry_count = nv->port_down_retry_count; if (qlport_down_retry) ha->port_down_retry_count = qlport_down_retry; /* Set login_retry_count */ ha->login_retry_count = nv->retry_count; if (ha->port_down_retry_count == nv->port_down_retry_count && ha->port_down_retry_count > 3) ha->login_retry_count = ha->port_down_retry_count; else if (ha->port_down_retry_count > (int)ha->login_retry_count) ha->login_retry_count = ha->port_down_retry_count; if (ql2xloginretrycount) ha->login_retry_count = ql2xloginretrycount; ha->binding_type = Bind; if (ha->binding_type != BIND_BY_PORT_NAME && ha->binding_type != BIND_BY_PORT_ID) { qla_printk(KERN_WARNING, ha, "Invalid binding type specified (%d), " "defaulting to BIND_BY_PORT_NAME!!!\n", ha->binding_type); ha->binding_type = BIND_BY_PORT_NAME; } /* * Setup ring parameters in initialization control block */ icb->request_q_outpointer = __constant_cpu_to_le16(0); icb->response_q_inpointer = __constant_cpu_to_le16(0); icb->request_q_length = cpu_to_le16(ha->request_q_length); icb->response_q_length = cpu_to_le16(ha->response_q_length); icb->request_q_address[0] = cpu_to_le32(LSD(ha->request_dma)); icb->request_q_address[1] = cpu_to_le32(MSD(ha->request_dma)); icb->response_q_address[0] = cpu_to_le32(LSD(ha->response_dma)); icb->response_q_address[1] = cpu_to_le32(MSD(ha->response_dma)); icb->lun_enables = __constant_cpu_to_le16(0); icb->command_resource_count = 0; icb->immediate_notify_resource_count = 0; icb->timeout = __constant_cpu_to_le16(0); if (IS_QLA2100(ha) || IS_QLA2200(ha)) { /* Enable RIO */ icb->firmware_options[0] &= ~BIT_3; icb->add_firmware_options[0] &= ~(BIT_3 | BIT_2 | BIT_1 | BIT_0); icb->add_firmware_options[0] |= BIT_2; icb->response_accumulation_timer = 3; icb->interrupt_delay_timer = 5; ha->flags.process_response_queue = 1; } else { /* Enable ZIO -- Support mode 5 only. */ timer_mode = icb->add_firmware_options[0] & (BIT_3 | BIT_2 | BIT_1 | BIT_0); icb->add_firmware_options[0] &= ~(BIT_3 | BIT_2 | BIT_1 | BIT_0); if (ql2xenablezio) timer_mode = BIT_2 | BIT_0; if (timer_mode == (BIT_2 | BIT_0)) { DEBUG2(printk("scsi(%ld): ZIO enabled; timer delay " "(%d).\n", ha->host_no, ql2xintrdelaytimer)); qla_printk(KERN_INFO, ha, "ZIO enabled; timer delay (%d).\n", ql2xintrdelaytimer); icb->add_firmware_options[0] |= timer_mode; icb->interrupt_delay_timer = ql2xintrdelaytimer; ha->flags.process_response_queue = 1; } } if (rval) { DEBUG2_3(printk(KERN_WARNING "scsi(%ld): NVRAM configuration failed!\n", ha->host_no)); } return (rval);}/** qla2x00_init_tgt_map* Initializes target map.** Input:* ha = adapter block pointer.** Output:* TGT_Q initialized*/static voidqla2x00_init_tgt_map(scsi_qla_host_t *ha){ uint32_t t; for (t = 0; t < MAX_TARGETS; t++) TGT_Q(ha, t) = (os_tgt_t *)NULL;}/** * qla2x00_alloc_fcport() - Allocate a generic fcport. * @ha: HA context * @flags: allocation flags * * Returns a pointer to the allocated fcport, or NULL, if none available. */fc_port_t *qla2x00_alloc_fcport(scsi_qla_host_t *ha, int flags){ fc_port_t *fcport; fcport = kmalloc(sizeof(fc_port_t), flags); if (fcport == NULL) return (fcport); /* Setup fcport template structure. */ memset(fcport, 0, sizeof (fc_port_t)); fcport->ha = ha; fcport->port_type = FCT_UNKNOWN; fcport->loop_id = FC_NO_LOOP_ID; fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; atomic_set(&fcport->state, FCS_UNCONFIGURED); fcport->flags = FCF_RLC_SUPPORT; INIT_LIST_HEAD(&fcport->fcluns); return (fcport);}/* * qla2x00_configure_loop * Updates Fibre Channel Device Database with what is actually on loop. * * Input: * ha = adapter block pointer. * * Returns:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?