qla_ip.c
来自「这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自」· C语言 代码 · 共 1,757 行 · 第 1/4 页
C
1,757 行
/* Therefore, only check mb0 for now */ if (/* mbxentry->status == CS_COMPLETE && */ mbxentry->mb0 == MBS_COMMAND_COMPLETE) { /* Login successful */ ipdev->flags |= IP_DEV_FLAG_PRESENT; } else if (mbxentry->mb0 == MBS_PORT_ID_IN_USE) { /* Different loop ID already assigned to port ID */ /* Use the one that is already assigned */ qla2x00_free_loopid(ha, ipdev->loop_id); ipdev->loop_id = mbxentry->mb1; /* Do logout first and then relogin */ qla2x00_ip_send_logout_port_iocb(ha, ipdev, 1); qla2x00_ip_send_login_port_iocb(ha, ipdev, 1); } else if (mbxentry->mb0 == MBS_LOOP_ID_IN_USE) { /* Loop ID already used for different port ID */ /* Get a new loop ID and reissue login request */ status = qla2x00_reserve_loopid(ha, &ipdev->loop_id); if (status == QL_STATUS_SUCCESS) { qla2x00_ip_send_login_port_iocb(ha, ipdev, 1); } else { DEBUG12(printk("%s: out of loop IDs\n", __func__);) qla2x00_free_ip_block(ha, ipdev); } } else { /* Login failed, return resources */ DEBUG12(printk("%s: fabric login failed\n", __func__);) qla2x00_free_loopid(ha, ipdev->loop_id); qla2x00_free_ip_block(ha, ipdev); } }}/** * qla2x00_ip_inquiry() - Discover IP-capable adapters. * @adapter_num: adapter number to check (instance) * @inq_data: return bd_inquiry data of the discovered adapter * * This routine is called by the IP driver to discover adapters that support IP * and to get adapter parameters from the SCSI driver. * * Returns TRUE if the specified adapter supports IP. */#if defined (ISP2200)intqla2200_ip_inquiry(uint16_t adapter_num, struct bd_inquiry *inq_data)#elif defined(ISP2300)intqla2300_ip_inquiry(uint16_t adapter_num, struct bd_inquiry *inq_data)#endif{ scsi_qla_host_t *ha; /* Verify structure size and version */ if ((inq_data->length != BDI_LENGTH) || (inq_data->version != BDI_VERSION)) { DEBUG12(printk("%s: incompatable structure\n", __func__);) return (FALSE); } /* Find the specified host adapter */ for (ha = qla2x00_hostlist; ha && ha->instance != adapter_num; ha = ha->next); if (ha) { if (!ha->flags.online) return (FALSE); DEBUG12(printk("%s: found adapter %d\n", __func__, adapter_num);) /* Return inquiry data to backdoor IP driver */ set_bit(BDI_IP_SUPPORT, &inq_data->options); if (ha->flags.enable_64bit_addressing) set_bit(BDI_64BIT_ADDRESSING, &inq_data->options); inq_data->ha = ha; inq_data->risc_rec_q = ha->risc_rec_q; inq_data->risc_rec_q_size = IP_BUFFER_QUEUE_DEPTH; inq_data->link_speed = ha->current_speed; memcpy(inq_data->port_name, ha->ip_port_name, WWN_SIZE); inq_data->pdev = ha->pdev; inq_data->ip_enable_routine = qla2x00_ip_enable; inq_data->ip_disable_routine = qla2x00_ip_disable; inq_data->ip_add_buffers_routine = qla2x00_add_buffers; inq_data->ip_send_packet_routine = qla2x00_send_packet; inq_data->ip_tx_timeout_routine = qla2x00_tx_timeout; return (TRUE); } return (FALSE);}/** * qla2x00_ip_enable() - Create IP-driver/SCSI-driver IP connection. * @ha: SCSI driver HA context * @enable_data: bd_enable data describing the IP connection * * This routine is called by the IP driver to enable an IP connection to the * SCSI driver and to pass in IP driver parameters. * * The HA context is propagated with the specified @enable_data and the * Firmware is initialized for IP support. * * Returns TRUE if the IP connection was successfully enabled. */static intqla2x00_ip_enable(scsi_qla_host_t *ha, struct bd_enable *enable_data){ int status; DEBUG12(printk("%s: enable adapter %d\n", __func__, (int)ha->host_no);) status = FALSE; /* Verify structure size and version and adapter online */ if (!(ha->flags.online) || (enable_data->length != BDE_LENGTH) || (enable_data->version != BDE_VERSION)) { DEBUG12(printk("%s: incompatable structure or offline\n", __func__);) return (status); } /* Save parameters from IP driver */ ha->mtu = enable_data->mtu; ha->header_size = enable_data->header_size; ha->receive_buffers = enable_data->receive_buffers; ha->max_receive_buffers = enable_data->max_receive_buffers; ha->receive_buff_data_size = enable_data->receive_buff_data_size; if (test_bit(BDE_NOTIFY_ROUTINE, &enable_data->options)) { ha->notify_routine = enable_data->notify_routine; ha->notify_context = enable_data->notify_context; } ha->send_completion_routine = enable_data->send_completion_routine; ha->receive_packets_routine = enable_data->receive_packets_routine; ha->receive_packets_context = enable_data->receive_packets_context; /* Enable RISC IP support */ status = qla2x00_ip_initialize(ha); if (!status) { DEBUG12(printk("%s: IP initialization failed", __func__);) ha->notify_routine = NULL; } return (status);}/** * qla2x00_ip_disable() - Remove IP-driver/SCSI-driver IP connection. * @ha: SCSI driver HA context * * This routine is called by the IP driver to disable a previously created IP * connection. * * A Firmware call to disable IP support is issued. */static voidqla2x00_ip_disable(scsi_qla_host_t *ha){ int rval; static mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; DEBUG12(printk("%s: disable adapter %d\n", __func__, (int)ha->host_no);) /* Wait for a ready state from the adapter */ while (!ha->init_done || ha->dpc_active) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ); } /* Disable IP support */ ha->flags.enable_ip = FALSE; mcp->mb[0] = MBC_DISABLE_IP; mcp->out_mb = MBX_0; mcp->in_mb = MBX_0; mcp->tov = 30; mcp->flags = 0; rval = qla2x00_mailbox_command(ha, mcp); if (rval == QL_STATUS_SUCCESS) { /* IP disabled successful */ DEBUG12(printk(KERN_INFO "%s: successful\n", __func__);) } else { DEBUG12(printk(KERN_WARNING "%s: MBC_DISABLE_IP failed\n", __func__);) } /* Reset IP parameters */ ha->rec_entries_in = 0; ha->rec_entries_out = 0; ha->notify_routine = NULL;}/** * qla2x00_add_buffers() - Adds buffers to the receive buffer queue. * @ha: SCSI driver HA context * @rec_count: The number of receive buffers to add to the queue * @ha_locked: Flag indicating if the function is called with the hardware lock * * This routine is called by the IP driver to pass new buffers to the receive * buffer queue. */static voidqla2x00_add_buffers(scsi_qla_host_t *ha, uint16_t rec_count, int ha_locked){ int i; uint16_t rec_in; uint16_t handle; unsigned long flags = 0; device_reg_t *reg; struct risc_rec_entry *risc_rec_q; struct buffer_cb *bcbs; flags = 0; risc_rec_q = ha->risc_rec_q; rec_in = ha->rec_entries_in; bcbs = ha->receive_buffers; /* Set RISC owns buffer flag on new entries */ for (i = 0; i < rec_count; i++) { handle = risc_rec_q[rec_in].handle; set_bit(BCB_RISC_OWNS_BUFFER, &(bcbs[handle].state)); if (rec_in < IP_BUFFER_QUEUE_DEPTH - 1) rec_in++; else rec_in = 0; } /* Update RISC buffer pointer */ if (!ha_locked) spin_lock_irqsave(&ha->hardware_lock, flags); reg = ha->iobase; WRT_REG_WORD(®->mailbox8, rec_in); ha->rec_entries_in = rec_in; if (!ha_locked) spin_unlock_irqrestore(&ha->hardware_lock, flags);}/** * qla2x00_send_packet() - Transmit a send_cb. * @ha: SCSI driver HA context * @scb: The send_cb structure to send * * This routine is called by the IP driver to pass @scb (IP packet) to the ISP * for transmission. * * Returns QL_STATUS_SUCCESS if @scb was sent, QL_STATUS_RESOURCE_ERROR if the * RISC was too busy to send, or QL_STATUS_ERROR. */static intqla2x00_send_packet(scsi_qla_host_t *ha, struct send_cb *scb){ int i; uint16_t cnt; uint16_t temp; uint32_t handle; unsigned long flags; struct ip_cmd_entry *ipcmd_entry; struct sk_buff *skb; device_reg_t *reg; DEBUG12(printk("%s: enter\n", __func__);) skb = scb->skb; reg = ha->iobase; /* Check adapter state */ if (!ha->flags.online) { return (QL_STATUS_ERROR); } /* Send marker if required */ if (ha->marker_needed != 0) { if(qla2x00_marker(ha, 0, 0, MK_SYNC_ALL) != QLA2X00_SUCCESS) { printk(KERN_WARNING "%s: Unable to issue marker.\n", __func__); return (QL_STATUS_ERROR); } ha->marker_needed = 0; } /* Acquire ring specific lock */ spin_lock_irqsave(&ha->hardware_lock, flags); if (ha->req_q_cnt < 4) { /* Update number of free request entries */#if defined(ISP2200) cnt = qla2x00_debounce_register(®->mailbox4);#else cnt = qla2x00_debounce_register(®->req_q_out);#endif if (ha->req_ring_index < cnt) ha->req_q_cnt = cnt - ha->req_ring_index; else ha->req_q_cnt = REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt); } if (ha->req_q_cnt >= 4) { /* Get tag handle for command */ handle = ha->current_scb_q_idx; for (i = 0; i < MAX_SEND_PACKETS; i++) { handle++; if (handle == MAX_SEND_PACKETS) handle = 0; if (ha->active_scb_q[handle] == NULL) { ha->current_scb_q_idx = handle; goto found_handle; } } } /* Low on resources, try again later */ spin_unlock_irqrestore(&ha->hardware_lock, flags); printk(KERN_WARNING "%s: Low on resources, try again later...\n", __func__); return (QL_STATUS_RESOURCE_ERROR);found_handle: /* Build ISP command packet */ ipcmd_entry = (struct ip_cmd_entry *)ha->request_ring_ptr; ipcmd_entry->entry_type = ET_IP_COMMAND_64; ipcmd_entry->entry_count = 1; ipcmd_entry->sys_define = 0; ipcmd_entry->entry_status = 0; ipcmd_entry->handle = handle; ipcmd_entry->reserved_1 = 0; /* Get destination loop ID for packet */ if (!qla2x00_get_ip_loopid(ha, scb->header, &ipcmd_entry->loop_id)) { /* Failed to get loop ID, convert packet to ARP */ if (qla2x00_convert_to_arp(ha, scb)) { /* Broadcast ARP */ ipcmd_entry->loop_id = BROADCAST; } else { /* Return packet */ spin_unlock_irqrestore(&ha->hardware_lock, flags); printk(KERN_WARNING "%s: Unable to determine loop id for " "destination.\n", __func__); return (QL_STATUS_ERROR); } } ipcmd_entry->timeout = 5; ipcmd_entry->control_flags = CF_WRITE; ipcmd_entry->reserved_2 = 0; ipcmd_entry->service_class = 0; ipcmd_entry->data_seg_count = 2; ipcmd_entry->ds.data_segs64[0].address[0] = LS_64BITS(scb->header_dma); ipcmd_entry->ds.data_segs64[0].address[1] = MS_64BITS(scb->header_dma); ipcmd_entry->ds.data_segs64[0].length = sizeof(struct packet_header); scb->skb_data_dma = pci_map_single(ha->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); ipcmd_entry->ds.data_segs64[1].address[0] = LS_64BITS(scb->skb_data_dma); ipcmd_entry->ds.data_segs64[1].address[1] = MS_64BITS(scb->skb_data_dma); ipcmd_entry->ds.data_segs64[1].length = skb->len; ipcmd_entry->byte_count = skb->len + sizeof(struct packet_header); /* Adjust ring index. */ ha->req_ring_index++; if (ha->req_ring_index == REQUEST_ENTRY_CNT) { ha->req_ring_index = 0; ha->request_ring_ptr = ha->request_ring; } else ha->request_ring_ptr++; ha->ipreq_cnt++; ha->req_q_cnt--; ha->active_scb_q[handle] = scb; /* Set chip new ring index. */#if defined(ISP2200) /* Added from 64bit start */ temp = CACHE_FLUSH(®->mailbox4); WRT_REG_WORD(®->mailbox4, ha->req_ring_index);#else /* Added from 64bit start */ temp = CACHE_FLUSH(®->req_q_in); WRT_REG_WORD(®->req_q_in, ha->req_ring_index);#endif spin_unlock_irqrestore(&ha->hardware_lock, flags); return (QL_STATUS_SUCCESS);}/** * qla2x00_tx_timeout() - Handle transmission timeout. * @ha: SCSI driver HA context * * This routine is called by the IP driver to handle packet transmission * timeouts. * * Returns QL_STATUS_SUCCESS if timeout handling completed successfully. */static intqla2x00_tx_timeout(scsi_qla_host_t *ha){ /* TODO: complete interface */ /* Reset RISC firmware for basic recovery */ printk(KERN_WARNING "%s: A transmission timeout occured - aborting ISP\n", __func__); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); return (QL_STATUS_SUCCESS);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?