📄 iph5526.c
字号:
case INBOUND_MFS_COMPLETION: DPRINTK("INBOUND_MFS_COMPLETION message received"); handle_MFS_interrupt(fi); break; case INBOUND_OOO_COMPLETION: DPRINTK("INBOUND_OOO_COMPLETION message received"); handle_OOO_interrupt(fi); break; case INBOUND_SFS_COMPLETION: DPRINTK("INBOUND_SFS_COMPLETION message received"); handle_SFS_interrupt(fi); break; case INBOUND_UNKNOWN_FRAME_I: DPRINTK("INBOUND_UNKNOWN_FRAME message received"); handle_Unknown_Frame_interrupt(fi); break; case INBOUND_BUSIED_FRAME: DPRINTK("INBOUND_BUSIED_FRAME message received"); handle_Busied_Frame_interrupt(fi); break; case FRAME_MGR_INTERRUPT: DPRINTK("FRAME_MGR_INTERRUPT message received"); handle_FM_interrupt(fi); break; case READ_STATUS: DPRINTK("READ_STATUS message received"); break; case SFS_BUF_WARN: DPRINTK("SFS_BUF_WARN message received"); handle_SFS_BUF_WARN_interrupt(fi); break; case MFS_BUF_WARN: DPRINTK("MFS_BUF_WARN message received"); handle_MFS_BUF_WARN_interrupt(fi); break; case IMQ_BUF_WARN: DPRINTK("IMQ_BUF_WARN message received"); handle_IMQ_BUF_WARN_interrupt(fi); break; case INBOUND_C1_TIMEOUT: DPRINTK("INBOUND_C1_TIMEOUT message received"); break; case BAD_SCSI_FRAME: DPRINTK("BAD_SCSI_FRAME message received"); handle_Bad_SCSI_Frame_interrupt(fi); break; case INB_SCSI_STATUS_COMPLETION: DPRINTK("INB_SCSI_STATUS_COMPL message received"); handle_Inbound_SCSI_Status_interrupt(fi); break; case INBOUND_SCSI_COMMAND: DPRINTK("INBOUND_SCSI_COMMAND message received"); handle_Inbound_SCSI_Command_interrupt(fi); break; case INBOUND_SCSI_DATA_COMPLETION: DPRINTK("INBOUND_SCSI_DATA message received"); /* Only for targets */ break; default: T_MSG("DEFAULT message received, type = %x", imq_int_type); return; } reset_latch(fi);}static void handle_OCI_interrupt(struct fc_info *fi){u_int *ptr_imq_entry;u_long transaction_id = 0;unsigned short status, seq_count, transmitted_ox_id;struct Scsi_Host *host = fi->host;struct iph5526_hostdata *hostdata = (struct iph5526_hostdata *)host->hostdata;Scsi_Cmnd *Cmnd;u_int tag; ENTER("handle_OCI_interrupt"); ptr_imq_entry = fi->q.ptr_imqe[fi->q.imq_cons_indx]; transaction_id = ntohl(*(ptr_imq_entry + 1)); status = ntohl(*(ptr_imq_entry + 2)) >> 16; seq_count = ntohl(*(ptr_imq_entry + 3)); DPRINTK("transaction_id= %x", (u_int)transaction_id); tag = transaction_id & 0xFFFF0000; transmitted_ox_id = transaction_id; /* The INT could be either due to TIME_OUT | BAD_ALPA. * But we check only for TimeOuts. Bad AL_PA will * caught by FM_interrupt handler. */ if ((status == OCM_TIMEOUT_OR_BAD_ALPA) && (!fi->g.port_discovery) && (!fi->g.perform_adisc)){ DPRINTK("Frame TimeOut on OX_ID = %x", (u_int)transaction_id); /* Is it a SCSI frame that is timing out ? Not a very good check... */ if ((transmitted_ox_id <= MAX_SCSI_OXID) && ((tag == FC_SCSI_BAD_TARGET) || (tag < 0x00FF0000))) { /* If it is a Bad AL_PA, we report it as BAD_TARGET. * Else, we allow the command to time-out. A Link * re-initialization could be taking place. */ if (tag == FC_SCSI_BAD_TARGET) { Cmnd = hostdata->cmnd_handler[transmitted_ox_id & MAX_SCSI_XID]; hostdata->cmnd_handler[transmitted_ox_id & MAX_SCSI_XID] = NULL; if (Cmnd != NULL) { Cmnd->result = DID_BAD_TARGET << 16; (*Cmnd->scsi_done) (Cmnd); } else T_MSG("NULL Command out of handler!"); } /* if Bad Target */ else { u_char missing_target = tag >> 16; struct fc_node_info *q = fi->node_info_list; /* A Node that we thought was logged in has gone * away. We are the optimistic kind and we keep * hoping that our dear little Target will come back * to us. For now we log him out. */ DPRINTK2("Missing Target = %d", missing_target); while (q != NULL) { if (q->target_id == missing_target) { T_MSG("Target %d Logged out", q->target_id); q->login = LOGIN_ATTEMPTED; if (fi->num_nodes > 0) fi->num_nodes--; tx_logi(fi, ELS_PLOGI, q->d_id); break; } else q = q->next; } } } /* End of SCSI frame timing out. */ else { if (seq_count > 1) { /* An IP frame was transmitted to a Bad AL_PA. Free up * the skb used. */ dev_kfree_skb_irq((struct sk_buff *)(bus_to_virt(transaction_id))); netif_wake_queue(fi->dev); } } /* End of IP frame timing out. */ } /* End of frame timing out. */ else { /* Frame was transmitted successfully. Check if it was an ELS * frame or an IP frame or a Bad_Target_Notification frame (in * case of a ptp_link). Ugly! */ if ((status == 0) && (seq_count == 0)) { u_int tag = transaction_id & 0xFFFF0000; /* Continue with port discovery after an ELS is successfully * transmitted. (status == 0). */ DPRINTK("tag = %x", tag); switch(tag) { case ELS_FLOGI: /* Letz use the Name Server instead */ fi->g.explore_fabric = TRUE; fi->g.port_discovery = FALSE; fi->g.alpa_list_index = MAX_NODES; add_to_ox_id_list(fi, transaction_id, tag); break; case ELS_PLOGI: if (fi->g.fabric_present && (fi->g.name_server == FALSE)) add_to_ox_id_list(fi,transaction_id,ELS_NS_PLOGI); else add_to_ox_id_list(fi, transaction_id, tag); break; case FC_SCSI_BAD_TARGET: Cmnd = hostdata->cmnd_handler[transmitted_ox_id & MAX_SCSI_XID]; hostdata->cmnd_handler[transmitted_ox_id & MAX_SCSI_XID] = NULL; if (Cmnd != NULL) { Cmnd->result = DID_BAD_TARGET << 16; (*Cmnd->scsi_done) (Cmnd); } else T_MSG("NULL Command out of handler!"); break; default: add_to_ox_id_list(fi, transaction_id, tag); } if (fi->g.alpa_list_index >= MAX_NODES) { if (fi->g.port_discovery == TRUE) { fi->g.port_discovery = FALSE; add_display_cache_timer(fi); } fi->g.alpa_list_index = MAX_NODES; } if (fi->g.port_discovery == TRUE) local_port_discovery(fi); } else { /* An IP frame has been successfully transmitted. * Free the skb that was used for this IP frame. */ if ((status == 0) && (seq_count > 1)) { dev_kfree_skb_irq((struct sk_buff *)(bus_to_virt(transaction_id))); netif_wake_queue(fi->dev); } } } LEAVE("handle_OCI_interrupt");}/* Right now we discard OOO frames */static void handle_OOO_interrupt(struct fc_info *fi){u_int *ptr_imq_entry;int queue_indx, offset, payload_size;int no_of_buffers = 1; /* header is in a separate buffer */ ptr_imq_entry = fi->q.ptr_imqe[fi->q.imq_cons_indx]; offset = ntohl(*(ptr_imq_entry + 1)) & 0x00000007; queue_indx = ntohl(*(ptr_imq_entry + 1)) & 0xFFFF0000; queue_indx = queue_indx >> 16; payload_size = ntohl(*(ptr_imq_entry + 2)) - TACHYON_HEADER_LEN; /* Calculate total number of buffers */ no_of_buffers += payload_size / MFS_BUFFER_SIZE; if (payload_size % MFS_BUFFER_SIZE) no_of_buffers++; /* provide Tachyon will another set of buffers */ fi->g.mfs_buffer_count += no_of_buffers; if (fi->g.mfs_buffer_count >= NO_OF_ENTRIES) { int count = fi->g.mfs_buffer_count / NO_OF_ENTRIES; fi->g.mfs_buffer_count -= NO_OF_ENTRIES * count; update_MFSBQ_indx(fi, count); }}static void handle_MFS_interrupt(struct fc_info *fi){u_int *ptr_imq_entry, *buff_addr;u_int type_of_frame, s_id;int queue_indx, offset, payload_size, starting_indx, starting_offset;u_short received_ox_id;int no_of_buffers = 1; /* header is in a separate buffer */struct sk_buff *skb;int wrap_around = FALSE, no_of_wrap_buffs = NO_OF_ENTRIES - 1; ENTER("handle_MFS_interrupt"); ptr_imq_entry = fi->q.ptr_imqe[fi->q.imq_cons_indx]; offset = ntohl(*(ptr_imq_entry + 1)) & 0x00000007; queue_indx = ntohl(*(ptr_imq_entry + 1)) & 0xFFFF0000; queue_indx = queue_indx >> 16; DPRINTK("queue_indx = %d, offset = %d\n", queue_indx, offset); payload_size = ntohl(*(ptr_imq_entry + 2)) - TACHYON_HEADER_LEN; DPRINTK("payload_size = %d", payload_size); /* Calculate total number of buffers */ no_of_buffers += payload_size / MFS_BUFFER_SIZE; if (payload_size % MFS_BUFFER_SIZE) no_of_buffers++; DPRINTK("no_of_buffers = %d", no_of_buffers); if ((no_of_buffers - 1) <= offset) { starting_offset = offset - (no_of_buffers - 1); starting_indx = queue_indx; } else { int temp = no_of_buffers - (offset + 1); int no_of_queues = temp / NO_OF_ENTRIES; starting_offset = temp % NO_OF_ENTRIES; if (starting_offset != 0) { no_of_wrap_buffs = starting_offset - 1; //exclude header starting_offset = NO_OF_ENTRIES - starting_offset; no_of_queues++; } starting_indx = queue_indx - no_of_queues; if (starting_indx < 0) { no_of_wrap_buffs -= (starting_indx + 1) * NO_OF_ENTRIES; starting_indx = MFSBQ_LENGTH + starting_indx; wrap_around = TRUE; } } DPRINTK("starting_indx = %d, starting offset = %d no_of_wrap_buffs = %d\n", starting_indx, starting_offset, no_of_wrap_buffs); /* Get Tachyon Header from first buffer */ buff_addr = bus_to_virt(ntohl(*(fi->q.ptr_mfsbq_base + starting_indx*NO_OF_ENTRIES + starting_offset))); /* extract Type of Frame */ type_of_frame = (u_int)ntohl(*(buff_addr + 4)) & 0xFF000000; s_id = (u_int)ntohl(*(buff_addr + 3)) & 0x00FFFFFF; received_ox_id = ntohl(*(buff_addr + 6)) >> 16; buff_addr += MFS_BUFFER_SIZE/4; DPRINTK("type_of_frame = %x, s_id = %x, ox_id = %x", type_of_frame, s_id, received_ox_id); switch(type_of_frame) { case TYPE_LLC_SNAP: skb = dev_alloc_skb(payload_size); if (skb == NULL) { printk(KERN_NOTICE "%s: In handle_MFS_interrupt() Memory squeeze, dropping packet.\n", fi->name); fi->fc_stats.rx_dropped++; fi->g.mfs_buffer_count += no_of_buffers; if (fi->g.mfs_buffer_count >= NO_OF_ENTRIES) { int count = fi->g.mfs_buffer_count / NO_OF_ENTRIES; fi->g.mfs_buffer_count -= NO_OF_ENTRIES * count; update_MFSBQ_indx(fi, count); } return; } if (wrap_around) { int wrap_size = no_of_wrap_buffs * MFS_BUFFER_SIZE; int tail_size = payload_size - wrap_size; DPRINTK("wrap_size = %d, tail_size = %d\n", wrap_size, tail_size); if (no_of_wrap_buffs) memcpy(skb_put(skb, wrap_size), buff_addr, wrap_size); buff_addr = bus_to_virt(ntohl(*(fi->q.ptr_mfsbq_base))); memcpy(skb_put(skb, tail_size), buff_addr, tail_size); } else memcpy(skb_put(skb, payload_size), buff_addr, payload_size); rx_net_mfs_packet(fi, skb); break; default: T_MSG("Unknown Frame Type received. Type = %x", type_of_frame); } /* provide Tachyon will another set of buffers */ fi->g.mfs_buffer_count += no_of_buffers; if (fi->g.mfs_buffer_count >= NO_OF_ENTRIES) { int count = fi->g.mfs_buffer_count / NO_OF_ENTRIES; fi->g.mfs_buffer_count -= NO_OF_ENTRIES * count; update_MFSBQ_indx(fi, count); } LEAVE("handle_MFS_interrupt");}static void handle_Unknown_Frame_interrupt(struct fc_info *fi){u_int *ptr_imq_entry;int queue_indx, offset; ENTER("handle_Unknown_Frame_interrupt"); ptr_imq_entry = fi->q.ptr_imqe[fi->q.imq_cons_indx]; offset = ntohl(*(ptr_imq_entry + 1)) & 0x00000007; queue_indx = ntohl(*(ptr_imq_entry + 1)) & 0xFFFF0000; queue_indx = queue_indx >> 16; /* We discard the "unknown" frame */ /* provide Tachyon will another set of buffers */ if (offset == (NO_OF_ENTRIES - 1)) update_SFSBQ_indx(fi); LEAVE("handle_Unknown_Frame_interrupt");}static void handle_Busied_Frame_interrupt(struct fc_info *fi){u_int *ptr_imq_entry;int queue_indx, offset; ENTER("handle_Busied_Frame_interrupt"); ptr_imq_entry = fi->q.ptr_imqe[fi->q.imq_cons_indx]; offset = ntohl(*(ptr_imq_entry + 1)) & 0x00000007; queue_indx = ntohl(*(ptr_imq_entry + 1)) & 0xFFFF0000; queue_indx = queue_indx >> 16; /* We discard the "busied" frame */ /* provide Tachyon will another set of buffers */ if (offset == (NO_OF_ENTRIES - 1)) update_SFSBQ_indx(fi); LEAVE("handle_Busied_Frame_interrupt");}static void handle_Bad_SCSI_Frame_interrupt(struct fc_info *fi){u_int *ptr_imq_entry, *buff_addr, *tach_header, *ptr_edb;u_int s_id, rctl, frame_class, burst_len, transfered_len, len = 0;int queue_indx, offset, payload_size, i;u_short ox_id, rx_id, x_id, mtu = 512;u_char target_id = 0xFF; ENTER("handle_Bad_SCSI_Frame_interrupt"); ptr_imq_entry = fi->q.ptr_imqe[fi->q.imq_cons_indx]; offset = ntohl(*(ptr_imq_entry + 1)) & 0x00000007; queue_indx = ntohl(*(ptr_imq_entry + 1)) & 0xFFFF0000; queue_indx = queue_indx >> 16; payload_size = ntohl(*(ptr_imq_entry + 2)); buff_addr = bus_to_virt(ntohl(*(fi->q.ptr_sfsbq_base + queue_indx*NO_OF_ENTRIES + offset))); rctl = ntohl(*(buff_addr + 2)) & 0xFF000000; s_id = ntohl(*(buff_addr + 3)) & 0x00FFFFFF; ox_id = ntohl(*(buff_addr + 6)) >> 16; rx_id = ntohl(*(buff_addr + 6)); x_id = ox_id & MAX_SCSI_XID; /* Any frame that comes in with OX_ID that matches an OX_ID
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -