iph5526.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:148k
- fi->g.e_i = 0;
- LEAVE("tx_logo");
- }
- static void tx_adisc(struct fc_info *fi, u_int cmnd_code, u_int d_id, u_short received_ox_id)
- {
- int int_required = 0;
- u_int r_ctl = RCTL_ELS_SCTL;
- u_int type = TYPE_ELS | EXCHANGE_RESPONDER | SEQUENCE_RESPONDER | FIRST_SEQUENCE | END_SEQUENCE;
- int size = sizeof(ADISC);
- u_int my_mtu = fi->g.my_mtu;
- fi->g.adisc.ls_cmnd_code = htonl(cmnd_code);
- fi->g.adisc.hard_address = htonl(0);
- fi->g.adisc.port_name_high = htonl(N_PORT_NAME_HIGH);
- fi->g.adisc.port_name_low = htonl(N_PORT_NAME_LOW);
- fi->g.adisc.node_name_high = htonl(NODE_NAME_HIGH);
- fi->g.adisc.node_name_low = htonl(NODE_NAME_LOW);
- fi->g.adisc.n_port_id = htonl(fi->g.my_id);
- if (cmnd_code == ELS_ADISC) {
- int_required = 1;
- r_ctl = RCTL_ELS_UCTL;
- type = TYPE_ELS | SEQUENCE_INITIATIVE | FIRST_SEQUENCE;
- }
- fi->g.type_of_frame = FC_ELS;
- memcpy(fi->g.els_buffer[fi->g.e_i], &fi->g.adisc, size);
- tx_exchange(fi, (char *)(fi->g.els_buffer[fi->g.e_i]),size, r_ctl, type, d_id, my_mtu, int_required, received_ox_id, cmnd_code);
- fi->g.e_i++;
- if (fi->g.e_i == MAX_PENDING_FRAMES)
- fi->g.e_i = 0;
- }
- static void tx_ls_rjt(struct fc_info *fi, u_int d_id, u_short received_ox_id, u_short reason_code, u_short expln_code)
- {
- int int_required = 0;
- u_int r_ctl = RCTL_ELS_SCTL;
- u_int type = TYPE_ELS | EXCHANGE_RESPONDER | LAST_SEQUENCE;
- int size = sizeof(LS_RJT);
- u_int my_mtu = fi->g.my_mtu;
- ENTER("tx_ls_rjt");
- fi->g.ls_rjt.cmnd_code = htonl(ELS_LS_RJT);
- fi->g.ls_rjt.reason_code = htonl((reason_code << 16) | expln_code);
- fi->g.type_of_frame = FC_ELS;
- memcpy(fi->g.els_buffer[fi->g.e_i], &fi->g.ls_rjt, size);
- tx_exchange(fi, (char *)(fi->g.els_buffer[fi->g.e_i]),size, r_ctl, type, d_id, my_mtu, int_required, received_ox_id, ELS_LS_RJT);
- fi->g.e_i++;
- if (fi->g.e_i == MAX_PENDING_FRAMES)
- fi->g.e_i = 0;
- LEAVE("tx_ls_rjt");
- }
- static void tx_abts(struct fc_info *fi, u_int d_id, u_short ox_id)
- {
- int int_required = 1;
- u_int r_ctl = RCTL_BASIC_ABTS;
- u_int type = TYPE_BLS | SEQUENCE_INITIATIVE | FIRST_SEQUENCE;
- int size = 0;
- u_int my_mtu = fi->g.my_mtu;
- ENTER("tx_abts");
- fi->g.type_of_frame = FC_BLS;
- tx_exchange(fi, NULL, size, r_ctl, type, d_id, my_mtu, int_required, ox_id, RCTL_BASIC_ABTS);
- LEAVE("tx_abts");
- }
- static u_int plogi_ok(struct fc_info *fi, u_int *buff_addr, int size)
- {
- int ret_code = 0;
- u_short mtu = ntohl(*(buff_addr + 10)) & 0x00000FFF;
- u_short class3 = ntohl(*(buff_addr + 25)) >> 16;
- u_short class3_conc_seq = ntohl(*(buff_addr + 27)) >> 16;
- u_short open_seq = ntohl(*(buff_addr + 28)) >> 16;
- DPRINTK1("mtu = %x class3 = %x conc_seq = %x open_seq = %x", mtu, class3, class3_conc_seq, open_seq);
- size -= TACHYON_HEADER_LEN;
- if (!(class3 & 0x8000)) {
- DPRINTK1("Received PLOGI with class3 = %x", class3);
- ret_code = (LOGICAL_ERR << 16) | NO_EXPLN;
- return ret_code;
- }
- if (mtu < 256) {
- DPRINTK1("Received PLOGI with MTU set to %x", mtu);
- ret_code = (LOGICAL_ERR << 16) | RECV_FIELD_SIZE;
- return ret_code;
- }
- if (size != PLOGI_LEN) {
- DPRINTK1("Received PLOGI of size %x", size);
- ret_code = (LOGICAL_ERR << 16) | INV_PAYLOAD_LEN;
- return ret_code;
- }
- if (class3_conc_seq == 0) {
- DPRINTK1("Received PLOGI with conc_seq == 0");
- ret_code = (LOGICAL_ERR << 16) | CONC_SEQ;
- return ret_code;
- }
- if (open_seq == 0) {
- DPRINTK1("Received PLOGI with open_seq == 0");
- ret_code = (LOGICAL_ERR << 16) | NO_EXPLN;
- return ret_code;
- }
- /* Could potentially check for more fields, but might end up
- not talking to most of the devices. ;-) */
- /* Things that could get checked are:
- common_features = 0x8800
- total_concurrent_seq = at least 1
- */
- return ret_code;
- }
- static void tx_acc(struct fc_info *fi, u_int d_id, u_short received_ox_id)
- {
- int int_required = 0;
- u_int r_ctl = RCTL_ELS_SCTL;
- u_int type = TYPE_ELS | EXCHANGE_RESPONDER | LAST_SEQUENCE;
- int size = sizeof(ACC);
- u_int my_mtu = fi->g.my_mtu;
- ENTER("tx_acc");
- fi->g.acc.cmnd_code = htonl(ELS_ACC);
- fi->g.type_of_frame = FC_ELS;
- memcpy(fi->g.els_buffer[fi->g.e_i], &fi->g.acc, size);
- tx_exchange(fi, (char *)(fi->g.els_buffer[fi->g.e_i]),size, r_ctl, type, d_id, my_mtu, int_required, received_ox_id, ELS_ACC);
- fi->g.e_i++;
- if (fi->g.e_i == MAX_PENDING_FRAMES)
- fi->g.e_i = 0;
- LEAVE("tx_acc");
- }
- static void tx_name_server_req(struct fc_info *fi, u_int req)
- {
- int int_required = 1, i, size = 0;
- u_short ox_id = OX_ID_FIRST_SEQUENCE;
- u_int type = TYPE_FC_SERVICES | SEQUENCE_INITIATIVE | FIRST_SEQUENCE;
- u_int r_ctl = FC4_DEVICE_DATA | UNSOLICITED_CONTROL;
- u_int my_mtu = fi->g.my_mtu, d_id = DIRECTORY_SERVER;
- CT_HDR ct_hdr;
- ENTER("tx_name_server_req");
- /* Fill up CT_Header */
- ct_hdr.rev_in_id = htonl(FC_CT_REV);
- ct_hdr.fs_type = DIRECTORY_SERVER_APP;
- ct_hdr.fs_subtype = NAME_SERVICE;
- ct_hdr.options = 0;
- ct_hdr.resv1 = 0;
- ct_hdr.cmnd_resp_code = htons(req >> 16);
- ct_hdr.max_res_size = 0;
- ct_hdr.resv2 = 0;
- ct_hdr.reason_code = 0;
- ct_hdr.expln_code = 0;
- ct_hdr.vendor_unique = 0;
-
- fi->g.type_of_frame = FC_ELS;
- switch(req) {
- case FCS_RFC_4:
- memcpy(&(fi->g.rfc_4.ct_hdr), &ct_hdr, sizeof(CT_HDR));
- fi->g.rfc_4.s_id = htonl(fi->g.my_id);
- for (i = 0; i < 32; i++)
- fi->g.rfc_4.bit_map[i] = 0;
- /* We support IP & SCSI */
- fi->g.rfc_4.bit_map[2] = 0x01;
- fi->g.rfc_4.bit_map[3] = 0x20;
- size = sizeof(RFC_4);
- memcpy(fi->g.els_buffer[fi->g.e_i], &fi->g.rfc_4, size);
- tx_exchange(fi, (char *)(fi->g.els_buffer[fi->g.e_i]),size, r_ctl, type, d_id, my_mtu, int_required, ox_id, req);
- break;
- case FCS_GP_ID4:
- memcpy(&(fi->g.gp_id4.ct_hdr), &ct_hdr, sizeof(CT_HDR));
- fi->g.gp_id4.port_type = htonl(PORT_TYPE_NX_PORTS);
- size = sizeof(GP_ID4);
- memcpy(fi->g.els_buffer[fi->g.e_i], &fi->g.gp_id4, size);
- tx_exchange(fi, (char *)(fi->g.els_buffer[fi->g.e_i]),size, r_ctl, type, d_id, my_mtu, int_required, ox_id, req);
- break;
- }
- fi->g.e_i++;
- if (fi->g.e_i == MAX_PENDING_FRAMES)
- fi->g.e_i = 0;
- LEAVE("tx_name_server_req");
- }
- static void tx_scr(struct fc_info *fi)
- {
- int int_required = 1, size = sizeof(SCR);
- u_short ox_id = OX_ID_FIRST_SEQUENCE;
- u_int type = TYPE_ELS | SEQUENCE_INITIATIVE | FIRST_SEQUENCE;
- u_int r_ctl = RCTL_ELS_UCTL;
- u_int my_mtu = fi->g.my_mtu, d_id = FABRIC_CONTROLLER;
- ENTER("tx_scr");
- fi->g.scr.cmnd_code = htonl(ELS_SCR);
- fi->g.scr.reg_function = htonl(FULL_REGISTRATION);
- fi->g.type_of_frame = FC_ELS;
- memcpy(fi->g.els_buffer[fi->g.e_i], &fi->g.scr, size);
- tx_exchange(fi, (char *)(fi->g.els_buffer[fi->g.e_i]),size, r_ctl, type, d_id, my_mtu, int_required, ox_id, ELS_SCR);
- fi->g.e_i++;
- if (fi->g.e_i == MAX_PENDING_FRAMES)
- fi->g.e_i = 0;
- LEAVE("tx_scr");
- }
- static void perform_adisc(struct fc_info *fi)
- {
- int count = 0;
- /* Will be set to TRUE when timer expires in a PLDA environment.
- */
- fi->g.port_discovery = FALSE;
- if (fi->node_info_list) {
- struct fc_node_info *temp_list = fi->node_info_list;
- while(temp_list) {
- /* Tx ADISC to all non-fabric based
- * entities.
- */
- if ((temp_list->d_id & 0xFF0000) != 0xFF0000)
- tx_adisc(fi, ELS_ADISC, temp_list->d_id, OX_ID_FIRST_SEQUENCE);
- temp_list = temp_list->next;
- udelay(20);
- count++;
- }
- }
- /* Perform Port Discovery after timer expires.
- * We are giving time for the ADISCed nodes to respond
- * so that we dont have to perform PLOGI to those whose
- * login are _still_ valid.
- */
- fi->explore_timer.function = port_discovery_timer;
- fi->explore_timer.data = (unsigned long)fi;
- fi->explore_timer.expires = RUN_AT((count*3*HZ)/100);
- init_timer(&fi->explore_timer);
- add_timer(&fi->explore_timer);
- }
- static void explore_fabric(struct fc_info *fi, u_int *buff_addr)
- {
- u_int *addr = buff_addr + 12; /* index into payload */
- u_char control_code;
- u_int d_id;
- int count = 0;
- ENTER("explore_fabric");
- DPRINTK1("entering explore_fabric");
- /*fi->g.perform_adisc = TRUE;
- fi->g.explore_fabric = TRUE;
- perform_adisc(fi);*/
-
- do {
- d_id = ntohl(*addr) & 0x00FFFFFF;
- if (d_id != fi->g.my_id) {
- if (sid_logged_in(fi, d_id) == NODE_NOT_PRESENT)
- tx_logi(fi, ELS_PLOGI, d_id);
- else
- if (sid_logged_in(fi, d_id) == NODE_LOGGED_OUT)
- tx_adisc(fi, ELS_ADISC, d_id, OX_ID_FIRST_SEQUENCE);
- count++;
- }
- control_code = (ntohl(*addr) & 0xFF000000) >> 24;
- addr++;
- DPRINTK1("cc = %x, d_id = %x", control_code, d_id);
- } while (control_code != 0x80);
-
- fi->explore_timer.function = fabric_explore_timer;
- fi->explore_timer.data = (unsigned long)fi;
- /* We give 30 msec for each device to respond and then send out
- * our SCSI enquiries.
- */
- fi->explore_timer.expires = RUN_AT((count*3*HZ)/100);
- init_timer(&fi->explore_timer);
- add_timer(&fi->explore_timer);
- DPRINTK1("leaving explore_fabric");
- LEAVE("explore_fabric");
- }
- static void fabric_explore_timer(unsigned long data)
- {
- struct fc_info *fi = (struct fc_info*)data;
- del_timer(&fi->explore_timer);
- if ((fi->g.loop_up == TRUE) && (fi->g.ptp_up == FALSE)) {
- /* Initiate Local Port Discovery on the Local Loop.
- */
- fi->g.port_discovery = TRUE;
- fi->g.alpa_list_index = 1;
- local_port_discovery(fi);
- }
- fi->g.explore_fabric = FALSE;
- return;
- }
- static void port_discovery_timer(unsigned long data)
- {
- struct fc_info *fi = (struct fc_info*)data;
- del_timer(&fi->explore_timer);
-
- if ((fi->g.loop_up == TRUE) && (fi->g.explore_fabric != TRUE)) {
- fi->g.port_discovery = TRUE;
- fi->g.alpa_list_index = 1;
- local_port_discovery(fi);
- }
- fi->g.perform_adisc = FALSE;
- return;
- }
- static void add_to_ox_id_list(struct fc_info *fi, u_int transaction_id, u_int cmnd_code)
- {
- struct ox_id_els_map *p, *q = fi->ox_id_list, *r = NULL;
- int size = sizeof(struct ox_id_els_map);
- while (q != NULL) {
- r = q;
- q = q->next;
- }
- p = (struct ox_id_els_map *)kmalloc(size, GFP_ATOMIC);
- if (p == NULL) {
- T_MSG("kmalloc failed in add_to_ox_id_list()");
- return;
- }
- p->ox_id = transaction_id;
- p->els = cmnd_code;
- p->next = NULL;
- if (fi->ox_id_list == NULL)
- fi->ox_id_list = p;
- else
- r->next = p;
- return;
- }
- static u_int remove_from_ox_id_list(struct fc_info *fi, u_short received_ox_id)
- {
- struct ox_id_els_map *p = fi->ox_id_list, *q = fi->ox_id_list;
- u_int els_type;
- while (q != NULL) {
- if (q->ox_id == received_ox_id) {
- if (q == fi->ox_id_list)
- fi->ox_id_list = fi->ox_id_list->next;
- else
- if (q->next == NULL)
- p->next = NULL;
- else
- p->next = q->next;
- els_type = q->els;
- kfree(q);
- return els_type;
- }
- p = q;
- q = q->next;
- }
- if (q == NULL)
- DPRINTK2("Could not find ox_id %x in ox_id_els_map", received_ox_id);
- return 0;
- }
- static void build_tachyon_header(struct fc_info *fi, u_int my_id, u_int r_ctl, u_int d_id, u_int type, u_char seq_id, u_char df_ctl, u_short ox_id, u_short rx_id, char *data)
- {
- u_char alpa = d_id & 0x0000FF;
- u_int dest_ddaa = d_id &0xFFFF00;
- ENTER("build_tachyon_header");
- DPRINTK("d_id = %x, my_ddaa = %x", d_id, fi->g.my_ddaa);
- /* Does it have to go to/thru a Fabric? */
- if ((dest_ddaa != 0) && ((d_id == F_PORT) || (fi->g.fabric_present && (dest_ddaa != fi->g.my_ddaa))))
- alpa = 0x00;
- fi->g.tach_header.resv = 0x00000000;
- fi->g.tach_header.sof_and_eof = SOFI3 | EOFN;
- fi->g.tach_header.dest_alpa = alpa;
- /* Set LCr properly to have enuff credit */
- if (alpa == REPLICATE)
- fi->g.tach_header.lcr_and_time_stamp = htons(0xC00);/* LCr=3 */
- else
- fi->g.tach_header.lcr_and_time_stamp = 0;
- fi->g.tach_header.r_ctl_and_d_id = htonl(r_ctl | d_id);
- fi->g.tach_header.vc_id_and_s_id = htonl(my_id);
- fi->g.tach_header.type_and_f_cntl = htonl(type);
- fi->g.tach_header.seq_id = seq_id;
- fi->g.tach_header.df_cntl = df_ctl;
- fi->g.tach_header.seq_cnt = 0;
- fi->g.tach_header.ox_id = htons(ox_id);
- fi->g.tach_header.rx_id = htons(rx_id);
- fi->g.tach_header.ro = 0;
- if (data) {
- /* We use the Seq_Count to keep track of IP frames in the
- * OCI_interrupt handler. Initial Seq_Count of IP frames is 1.
- */
- if (fi->g.type_of_frame == FC_BROADCAST)
- fi->g.tach_header.seq_cnt = htons(0x1);
- else
- fi->g.tach_header.seq_cnt = htons(0x2);
- fi->g.tach_header.nw_header.d_naa = htons(0x1000);
- fi->g.tach_header.nw_header.s_naa = htons(0x1000);
- memcpy(&(fi->g.tach_header.nw_header.dest_high), data, 2);
- memcpy(&(fi->g.tach_header.nw_header.dest_low), data + 2, 4);
- memcpy(&(fi->g.tach_header.nw_header.source_high), data + 6, 2);
- memcpy(&(fi->g.tach_header.nw_header.source_low), data + 8, 4);
- }
- LEAVE("build_tachyon_header");
- }
- static void build_EDB(struct fc_info *fi, char *data, u_short flags, u_short len)
- {
- fi->g.edb.buf_addr = ntohl((u_int)virt_to_bus(data));
- fi->g.edb.ehf = ntohs(flags);
- if (len % 4)
- len += (4 - (len % 4));
- fi->g.edb.buf_len = ntohs(len);
- }
- static void build_ODB(struct fc_info *fi, u_char seq_id, u_int d_id, u_int len, u_int cntl, u_short mtu, u_short ox_id, u_short rx_id, int NW_header, int int_required, u_int frame_class)
- {
- fi->g.odb.seq_d_id = htonl(seq_id << 24 | d_id);
- fi->g.odb.tot_len = len;
- if (NW_header)
- fi->g.odb.tot_len += NW_HEADER_LEN;
- if (fi->g.odb.tot_len % 4)
- fi->g.odb.tot_len += (4 - (fi->g.odb.tot_len % 4));
- fi->g.odb.tot_len = htonl(fi->g.odb.tot_len);
- switch(int_required) {
- case NO_COMP_AND_INT:
- fi->g.odb.cntl = htons(ODB_CLASS_3 | ODB_EE_CREDIT | ODB_NO_INT | ODB_NO_COMP | cntl);
- break;
- case INT_AND_COMP_REQ:
- fi->g.odb.cntl = htons(ODB_CLASS_3 | ODB_EE_CREDIT | cntl);
- break;
- case NO_INT_COMP_REQ:
- fi->g.odb.cntl = htons(ODB_CLASS_3 | ODB_EE_CREDIT | ODB_NO_INT | cntl);
- break;
- }
- fi->g.odb.rx_id = htons(rx_id);
- fi->g.odb.cs_enable = 0;
- fi->g.odb.cs_seed = htons(1);
- fi->g.odb.hdr_addr = htonl(virt_to_bus(fi->q.ptr_tachyon_header[fi->q.tachyon_header_indx]));
- fi->g.odb.frame_len = htons(mtu);
- if (NW_header) {
- /* The pointer to the sk_buff is in here. Freed up when the
- * OCI_interrupt is received.
- */
- fi->g.odb.trans_id = htonl(frame_class);
- fi->g.odb.hdr_len = TACHYON_HEADER_LEN + NW_HEADER_LEN;
- }
- else {
- /* helps in tracking transmitted OX_IDs */
- fi->g.odb.trans_id = htonl((frame_class & 0xFFFF0000) | ox_id);
- fi->g.odb.hdr_len = TACHYON_HEADER_LEN;
- }
- fi->g.odb.hdr_len = htons(fi->g.odb.hdr_len);
-
- fi->g.odb.edb_addr = htonl(virt_to_bus(fi->q.ptr_edb[fi->q.edb_buffer_indx]));
- }
- static void fill_login_frame(struct fc_info *fi, u_int logi)
- {
- int i;
- fi->g.login.ls_cmnd_code= htonl(logi);
- fi->g.login.fc_ph_version = htons(PH_VERSION);
- if (fi->g.loop_up)
- fi->g.login.buff_to_buff_credit = htons(LOOP_BB_CREDIT);
- else
- if (fi->g.ptp_up)
- fi->g.login.buff_to_buff_credit = htons(PT2PT_BB_CREDIT);
- if ((logi != ELS_FLOGI) || (logi == ELS_ACC))
- fi->g.login.common_features = htons(PLOGI_C_F);
- else
- if (logi == ELS_FLOGI)
- fi->g.login.common_features = htons(FLOGI_C_F);
- fi->g.login.recv_data_field_size = htons(TACH_FRAME_SIZE);
- fi->g.login.n_port_total_conc_seq = htons(CONCURRENT_SEQUENCES);
- fi->g.login.rel_off_by_info_cat = htons(RO_INFO_CATEGORY);
- fi->g.login.ED_TOV = htonl(E_D_TOV);
- fi->g.login.n_port_name_high = htonl(N_PORT_NAME_HIGH);
- fi->g.login.n_port_name_low = htonl(N_PORT_NAME_LOW);
- fi->g.login.node_name_high = htonl(NODE_NAME_HIGH);
- fi->g.login.node_name_low = htonl(NODE_NAME_LOW);
-
- /* Fill Class 1 parameters */
- fi->g.login.c_of_s[0].service_options = htons(0);
- fi->g.login.c_of_s[0].initiator_ctl = htons(0);
- fi->g.login.c_of_s[0].recipient_ctl = htons(0);
- fi->g.login.c_of_s[0].recv_data_field_size = htons(0);
- fi->g.login.c_of_s[0].concurrent_sequences = htons(0);
- fi->g.login.c_of_s[0].n_port_end_to_end_credit = htons(0);
- fi->g.login.c_of_s[0].open_seq_per_exchange = htons(0);
- fi->g.login.c_of_s[0].resv = htons(0);
- /* Fill Class 2 parameters */
- fi->g.login.c_of_s[1].service_options = htons(0);
- fi->g.login.c_of_s[1].initiator_ctl = htons(0);
- fi->g.login.c_of_s[1].recipient_ctl = htons(0);
- fi->g.login.c_of_s[1].recv_data_field_size = htons(0);
- fi->g.login.c_of_s[1].concurrent_sequences = htons(0);
- fi->g.login.c_of_s[1].n_port_end_to_end_credit = htons(0);
- fi->g.login.c_of_s[1].open_seq_per_exchange = htons(0);
- fi->g.login.c_of_s[1].resv = htons(0);
- /* Fill Class 3 parameters */
- if (logi == ELS_FLOGI)
- fi->g.login.c_of_s[2].service_options = htons(SERVICE_VALID | SEQUENCE_DELIVERY);
- else
- fi->g.login.c_of_s[2].service_options = htons(SERVICE_VALID);
- fi->g.login.c_of_s[2].initiator_ctl = htons(0);
- fi->g.login.c_of_s[2].recipient_ctl = htons(0);
- fi->g.login.c_of_s[2].recv_data_field_size = htons(TACH_FRAME_SIZE);
- fi->g.login.c_of_s[2].concurrent_sequences = htons(CLASS3_CONCURRENT_SEQUENCE);
- fi->g.login.c_of_s[2].n_port_end_to_end_credit = htons(0);
- fi->g.login.c_of_s[2].open_seq_per_exchange = htons(CLASS3_OPEN_SEQUENCE);
- fi->g.login.c_of_s[2].resv = htons(0);
-
- for(i = 0; i < 4; i++) {
- fi->g.login.resv[i] = 0;
- fi->g.login.vendor_version_level[i] = 0;
- }
- }
- /* clear the Interrupt Latch on the (i)chip, so that you can receive
- * Interrupts from Tachyon in future
- */
- static void reset_latch(struct fc_info *fi)
- {
- writel(readl(fi->i_r.ptr_ichip_hw_status_reg) | ICHIP_HSR_INT_LATCH, fi->i_r.ptr_ichip_hw_status_reg);
- }
- static void update_OCQ_indx(struct fc_info *fi)
- {
- fi->q.ocq_prod_indx++;
- if (fi->q.ocq_prod_indx == OCQ_LENGTH)
- fi->q.ocq_prod_indx = 0;
- writel(fi->q.ocq_prod_indx, fi->t_r.ptr_ocq_prod_indx_reg);
- }
- static void update_IMQ_indx(struct fc_info *fi, int count)
- {
- fi->q.imq_cons_indx += count;
- if (fi->q.imq_cons_indx >= IMQ_LENGTH)
- fi->q.imq_cons_indx -= IMQ_LENGTH;
- writel(fi->q.imq_cons_indx, fi->t_r.ptr_imq_cons_indx_reg);
- }
- static void update_SFSBQ_indx(struct fc_info *fi)
- {
- fi->q.sfsbq_prod_indx++;
- if (fi->q.sfsbq_prod_indx == SFSBQ_LENGTH)
- fi->q.sfsbq_prod_indx = 0;
- writel(fi->q.sfsbq_prod_indx, fi->t_r.ptr_sfsbq_prod_reg);
- }
- static void update_MFSBQ_indx(struct fc_info *fi, int count)
- {
- fi->q.mfsbq_prod_indx += count;
- if (fi->q.mfsbq_prod_indx >= MFSBQ_LENGTH)
- fi->q.mfsbq_prod_indx -= MFSBQ_LENGTH;
- writel(fi->q.mfsbq_prod_indx, fi->t_r.ptr_mfsbq_prod_reg);
- }
- static void update_tachyon_header_indx(struct fc_info *fi)
- {
- fi->q.tachyon_header_indx++;
- if (fi->q.tachyon_header_indx == NO_OF_TACH_HEADERS)
- fi->q.tachyon_header_indx = 0;
- }
- static void update_EDB_indx(struct fc_info *fi)
- {
- fi->q.edb_buffer_indx++;
- if (fi->q.edb_buffer_indx == EDB_LEN)
- fi->q.edb_buffer_indx = 0;
- }
- static int iph5526_open(struct net_device *dev)
- {
- netif_start_queue(dev);
- MOD_INC_USE_COUNT;
- return 0;
- }
- static int iph5526_close(struct net_device *dev)
- {
- netif_stop_queue(dev);
- MOD_DEC_USE_COUNT;
- return 0;
- }
- static void iph5526_timeout(struct net_device *dev)
- {
- struct fc_info *fi = (struct fc_info*)dev->priv;
- printk(KERN_WARNING "%s: timed out on send.n", dev->name);
- fi->fc_stats.rx_dropped++;
- dev->trans_start = jiffies;
- netif_wake_queue(dev);
- }
- static int iph5526_send_packet(struct sk_buff *skb, struct net_device *dev)
- {
- struct fc_info *fi = (struct fc_info*)dev->priv;
- int status = 0;
- short type = 0;
- u_long flags;
- struct fcllc *fcllc;
-
- ENTER("iph5526_send_packet");
-
- netif_stop_queue(dev);
- /* Strip off the pseudo header.
- */
- skb->data = skb->data + 2*FC_ALEN;
- skb->len = skb->len - 2*FC_ALEN;
- fcllc = (struct fcllc *)skb->data;
- type = ntohs(fcllc->ethertype);
- spin_lock_irqsave(&fi->fc_lock, flags);
- switch(type) {
- case ETH_P_IP:
- status = tx_ip_packet(skb, skb->len, fi);
- break;
- case ETH_P_ARP:
- status = tx_arp_packet(skb->data, skb->len, fi);
- break;
- default:
- T_MSG("WARNING!!! Received Unknown Packet Type... Discarding...");
- fi->fc_stats.rx_dropped++;
- break;
- }
- spin_unlock_irqrestore(&fi->fc_lock, flags);
- if (status) {
- fi->fc_stats.tx_bytes += skb->len;
- fi->fc_stats.tx_packets++;
- }
- else
- fi->fc_stats.rx_dropped++;
- dev->trans_start = jiffies;
- /* We free up the IP buffers in the OCI_interrupt handler.
- * status == 0 implies that the frame was not transmitted. So the
- * skb is freed here.
- */
- if ((type == ETH_P_ARP) || (status == 0))
- dev_kfree_skb(skb);
- else
- netif_wake_queue(dev);
- LEAVE("iph5526_send_packet");
- return 0;
- }
- static int iph5526_change_mtu(struct net_device *dev, int mtu)
- {
- return 0;
- }
- static int tx_ip_packet(struct sk_buff *skb, unsigned long len, struct fc_info *fi)
- {
- u_int d_id;
- int int_required = 1;
- u_int r_ctl = FC4_DEVICE_DATA | UNSOLICITED_DATA;
- u_int type = TYPE_LLC_SNAP;
- u_short ox_id = OX_ID_FIRST_SEQUENCE;
- u_int mtu;
- struct fc_node_info *q;
- ENTER("tx_ip_packet");
- q = look_up_cache(fi, skb->data - 2*FC_ALEN);
- if (q != NULL) {
- d_id = q->d_id;
- DPRINTK("Look-Up Cache Succeeded for d_id = %x", d_id);
- mtu = q->mtu;
- if (q->login == LOGIN_COMPLETED){
- fi->g.type_of_frame = FC_IP;
- return tx_exchange(fi, skb->data, len, r_ctl, type, d_id, mtu, int_required, ox_id, virt_to_bus(skb));
- }
-
- if (q->d_id == BROADCAST) {
- struct fc_node_info *p = fi->node_info_list;
- int return_value = FALSE;
- fi->g.type_of_frame = FC_BROADCAST;
- /* Do unicast to local nodes.
- */
- int_required = 0;
- while(p != NULL) {
- d_id = p->d_id;
- if ((d_id & 0xFFFF00) == fi->g.my_ddaa)
- return_value |= tx_exchange(fi, skb->data, len, r_ctl, type, d_id, fi->g.my_mtu, int_required, ox_id, TYPE_LLC_SNAP);
- p = p->next;
- }
- kfree(q);
- return return_value;
- }
-
- if (q->login != LOGIN_COMPLETED) {
- DPRINTK1("Node not logged in... Txing PLOGI to %x", d_id);
- /* FIXME: we are dumping the frame here */
- tx_logi(fi, ELS_PLOGI, d_id);
- }
- }
- DPRINTK2("Look-Up Cache Failed");
- LEAVE("tx_ip_packet");
- return 0;
- }
- static int tx_arp_packet(char *data, unsigned long len, struct fc_info *fi)
- {
- u_int opcode = data[ARP_OPCODE_0];
- u_int d_id;
- int int_required = 0, return_value = FALSE;
- u_int r_ctl = FC4_DEVICE_DATA | UNSOLICITED_DATA;
- u_int type = TYPE_LLC_SNAP;
- u_short ox_id = OX_ID_FIRST_SEQUENCE;
- u_int my_mtu = fi->g.my_mtu;
- ENTER("tx_arp_packet");
- opcode = opcode << 8 | data[ARP_OPCODE_1];
- fi->g.type_of_frame = FC_IP;
- if (opcode == ARPOP_REQUEST) {
- struct fc_node_info *q = fi->node_info_list;
- d_id = BROADCAST;
- return_value |= tx_exchange(fi, data, len, r_ctl, type, d_id, my_mtu, int_required, ox_id, TYPE_LLC_SNAP);
- /* Some devices support HW_TYPE 0x01 */
- memcpy(fi->g.arp_buffer, data - 2*FC_ALEN, len + 2*FC_ALEN);
- fi->g.arp_buffer[9 + 2*FC_ALEN] = 0x01;
- return_value |= tx_exchange(fi, (char *)(fi->g.arp_buffer + 2*FC_ALEN), len, r_ctl, type, d_id, my_mtu, int_required, ox_id, TYPE_LLC_SNAP);
- /* Do unicast to local nodes.
- */
- while(q != NULL) {
- fi->g.type_of_frame = FC_BROADCAST;
- d_id = q->d_id;
- if ((d_id & 0xFFFF00) == fi->g.my_ddaa) {
- return_value |= tx_exchange(fi, data, len, r_ctl, type, d_id, my_mtu, int_required, ox_id, TYPE_LLC_SNAP);
- // Some devices support HW_TYPE 0x01
- memcpy(fi->g.arp_buffer, data - 2*FC_ALEN, len + 2*FC_ALEN);
- fi->g.arp_buffer[9 + 2*FC_ALEN] = 0x01;
- return_value |= tx_exchange(fi, (char *)(fi->g.arp_buffer + 2*FC_ALEN), len, r_ctl, type, d_id, my_mtu, int_required, ox_id, TYPE_LLC_SNAP);
- }
- q = q->next;
- }
- return return_value;
- }
- else
- if (opcode == ARPOP_REPLY) {
- struct fc_node_info *q; u_int mtu;
- DPRINTK("We are sending out an ARP reply");
- q = look_up_cache(fi, data - 2*FC_ALEN);
- if (q != NULL) {
- d_id = q->d_id;
- DPRINTK("Look-Up Cache Succeeded for d_id = %x", d_id);
- mtu = q->mtu;
- if (q->login == LOGIN_COMPLETED){
- tx_exchange(fi, data, len, r_ctl, type, d_id, mtu, int_required, ox_id, TYPE_LLC_SNAP);
- /* Some devices support HW_TYPE 0x01 */
- memcpy(fi->g.arp_buffer, data - 2*FC_ALEN, len + 2*FC_ALEN);
- fi->g.arp_buffer[9 + 2*FC_ALEN] = 0x01;
- return tx_exchange(fi, (char *)(fi->g.arp_buffer + 2*FC_ALEN), len, r_ctl, type, d_id, my_mtu, int_required, ox_id, TYPE_LLC_SNAP);
- }
- else {
- DPRINTK1("Node not logged in... Txing PLOGI to %x", d_id);
- tx_logi(fi, ELS_PLOGI, d_id); /* FIXME: we are dumping the frame here */
- }
- }
- DPRINTK2("Look-Up Cache Failed");
- }
- else {
- T_MSG("Warning!!! Invalid Opcode in ARP Packet!");
- }
- LEAVE("tx_arp_packet");
- return 0;
- }
- static void rx_net_packet(struct fc_info *fi, u_char *buff_addr, int payload_size)
- {
- struct net_device *dev = fi->dev;
- struct sk_buff *skb;
- u_int skb_size = 0;
- struct fch_hdr fch;
- ENTER("rx_net_packet");
- skb_size = payload_size - TACHYON_HEADER_LEN;
- DPRINTK("skb_size = %d", skb_size);
- fi->fc_stats.rx_bytes += skb_size - 2;
- skb = dev_alloc_skb(skb_size);
- if (skb == NULL) {
- printk(KERN_NOTICE "%s: In rx_net_packet() Memory squeeze, dropping packet.n", dev->name);
- fi->fc_stats.rx_dropped++;
- return;
- }
- /* Skip over the Tachyon Frame Header.
- */
- buff_addr += TACHYON_HEADER_LEN;
- memcpy(fch.daddr, buff_addr + 2, FC_ALEN);
- memcpy(fch.saddr, buff_addr + 10, FC_ALEN);
- buff_addr += 2;
- memcpy(buff_addr, fch.daddr, FC_ALEN);
- memcpy(buff_addr + 6, fch.saddr, FC_ALEN);
- skb_reserve(skb, 2);
- memcpy(skb_put(skb, skb_size - 2), buff_addr, skb_size - 2);
- skb->dev = dev;
- skb->protocol = fc_type_trans(skb, dev);
- DPRINTK("protocol = %x", skb->protocol);
-
- /* Hmmm... to accept HW Type 0x01 as well...
- */
- if (skb->protocol == ntohs(ETH_P_ARP))
- skb->data[1] = 0x06;
- netif_rx(skb);
- dev->last_rx = jiffies;
- fi->fc_stats.rx_packets++;
- LEAVE("rx_net_packet");
- }
- static void rx_net_mfs_packet(struct fc_info *fi, struct sk_buff *skb)
- {
- struct net_device *dev = fi->dev;
- struct fch_hdr fch;
- ENTER("rx_net_mfs_packet");
- /* Construct your Hard Header */
- memcpy(fch.daddr, skb->data + 2, FC_ALEN);
- memcpy(fch.saddr, skb->data + 10, FC_ALEN);
- skb_pull(skb, 2);
- memcpy(skb->data, fch.daddr, FC_ALEN);
- memcpy(skb->data + 6, fch.saddr, FC_ALEN);
- skb->dev = dev;
- skb->protocol = fc_type_trans(skb, dev);
- DPRINTK("protocol = %x", skb->protocol);
- netif_rx(skb);
- dev->last_rx = jiffies;
- LEAVE("rx_net_mfs_packet");
- }
- unsigned short fc_type_trans(struct sk_buff *skb, struct net_device *dev)
- {
- struct fch_hdr *fch=(struct fch_hdr *)skb->data;
- struct fcllc *fcllc;
- skb->mac.raw = skb->data;
- fcllc = (struct fcllc *)(skb->data + sizeof(struct fch_hdr) + 2);
- skb_pull(skb,sizeof(struct fch_hdr) + 2);
- if(*fch->daddr & 1) {
- if(!memcmp(fch->daddr,dev->broadcast,FC_ALEN))
- skb->pkt_type = PACKET_BROADCAST;
- else
- skb->pkt_type = PACKET_MULTICAST;
- }
- else if(dev->flags & IFF_PROMISC) {
- if(memcmp(fch->daddr, dev->dev_addr, FC_ALEN))
- skb->pkt_type=PACKET_OTHERHOST;
- }
-
- /* Strip the SNAP header from ARP packets since we don't
- * pass them through to the 802.2/SNAP layers.
- */
- if (fcllc->dsap == EXTENDED_SAP &&
- (fcllc->ethertype == ntohs(ETH_P_IP) ||
- fcllc->ethertype == ntohs(ETH_P_ARP))) {
- skb_pull(skb, sizeof(struct fcllc));
- return fcllc->ethertype;
- }
- return ntohs(ETH_P_802_2);
- }
- static int tx_exchange(struct fc_info *fi, char *data, u_int len, u_int r_ctl, u_int type, u_int d_id, u_int mtu, int int_required, u_short tx_ox_id, u_int frame_class)
- {
- u_char df_ctl;
- int NW_flag = 0, h_size, return_value;
- u_short rx_id = RX_ID_FIRST_SEQUENCE;
- u_int tachyon_status;
- u_int my_id = fi->g.my_id;
- ENTER("tx_exchange");
- tachyon_status = readl(fi->t_r.ptr_tach_status_reg);
- DPRINTK("Tachyon Status = %x len = %d MTU = %d", tachyon_status, len, mtu);
- if (tachyon_status & OSM_FROZEN) {
- reset_tachyon(fi, ERROR_RELEASE);
- reset_tachyon(fi, OCQ_RESET);
- DPRINTK("Tachyon Status = %x len = %d MTU = %d", tachyon_status, len, mtu);
- }
- if (tx_ox_id == OX_ID_FIRST_SEQUENCE) {
- switch(fi->g.type_of_frame) {
- case FC_SCSI_READ:
- tx_ox_id = fi->g.scsi_oxid | SCSI_READ_BIT;
- break;
- case FC_SCSI_WRITE:
- tx_ox_id = fi->g.scsi_oxid;
- break;
- default:
- tx_ox_id = fi->g.ox_id;
- break;
- }
- }
- else {
- switch(fi->g.type_of_frame) {
- case FC_SCSI_READ:
- rx_id = fi->g.scsi_oxid | SCSI_READ_BIT;
- break;
- case FC_SCSI_WRITE:
- rx_id = fi->g.scsi_oxid;
- break;
- case FC_BLS:
- rx_id = RX_ID_FIRST_SEQUENCE;
- break;
- default:
- rx_id = fi->g.ox_id;
- break;
- }
- }
- if (type == TYPE_LLC_SNAP) {
- df_ctl = 0x20;
- NW_flag = 1;
- /* Multi Frame Sequence ? If yes, set RO bit */
- if (len > mtu)
- type |= RELATIVE_OFF_PRESENT;
- build_tachyon_header(fi, my_id, r_ctl, d_id, type, fi->g.seq_id, df_ctl, tx_ox_id, rx_id, data - 2*FC_ALEN);
- }
- else {
- df_ctl = 0;
- /* Multi Frame Sequence ? If yes, set RO bit */
- if (len > mtu)
- type |= RELATIVE_OFF_PRESENT;
- build_tachyon_header(fi, my_id, r_ctl, d_id, type, fi->g.seq_id, df_ctl, tx_ox_id, rx_id, NULL);
- }
- /* Get free Tachyon Headers and EDBs */
- if (get_free_header(fi) || get_free_EDB(fi))
- return 0;
- if ((type & 0xFF000000) == TYPE_LLC_SNAP) {
- h_size = TACHYON_HEADER_LEN + NW_HEADER_LEN;
- memcpy(fi->q.ptr_tachyon_header[fi->q.tachyon_header_indx], &(fi->g.tach_header), h_size);
- }
- else
- memcpy(fi->q.ptr_tachyon_header[fi->q.tachyon_header_indx], &(fi->g.tach_header), TACHYON_HEADER_LEN);
- return_value = tx_sequence(fi, data, len, mtu, d_id, tx_ox_id, rx_id, fi->g.seq_id, NW_flag, int_required, frame_class);
-
- switch(fi->g.type_of_frame) {
- case FC_SCSI_READ:
- case FC_SCSI_WRITE:
- update_scsi_oxid(fi);
- break;
- case FC_BLS:
- break;
- default:
- fi->g.ox_id++;
- if (fi->g.ox_id == 0xFFFF)
- fi->g.ox_id = NOT_SCSI_XID;
- break;
- }
- if (fi->g.seq_id == MAX_SEQ_ID)
- fi->g.seq_id = 0;
- else
- fi->g.seq_id++;
- LEAVE("tx_exchange");
- return return_value;
- }
- static int tx_sequence(struct fc_info *fi, char *data, u_int len, u_int mtu, u_int d_id, u_short ox_id, u_short rx_id, u_char seq_id, int NW_flag, int int_required, u_int frame_class)
- {
- u_int cntl = 0;
- int return_value;
- ENTER("tx_sequence");
- build_EDB(fi, data, EDB_END, len);
- memcpy(fi->q.ptr_edb[fi->q.edb_buffer_indx], &(fi->g.edb), sizeof(EDB));
- build_ODB(fi, seq_id, d_id, len, cntl, mtu, ox_id, rx_id, NW_flag, int_required, frame_class);
- memcpy(fi->q.ptr_odb[fi->q.ocq_prod_indx], &(fi->g.odb), sizeof(ODB));
- if (fi->g.link_up != TRUE) {
- DPRINTK2("Fibre Channel Link not up. Dropping Exchange!");
- return_value = FALSE;
- }
- else {
- /* To be on the safe side, a check should be included
- * at this point to check if we are overrunning
- * Tachyon.
- */
- update_OCQ_indx(fi);
- return_value = TRUE;
- }
- update_EDB_indx(fi);
- update_tachyon_header_indx(fi);
- LEAVE("tx_sequence");
- return return_value;
- }
- static int get_free_header(struct fc_info *fi)
- {
- u_short temp_ox_id;
- u_int *tach_header, initial_indx = fi->q.tachyon_header_indx;
- /* Check if the header is in use.
- * We could have an outstanding command.
- * We should find a free slot as we can queue a
- * maximum of 32 SCSI commands only.
- */
- tach_header = fi->q.ptr_tachyon_header[fi->q.tachyon_header_indx];
- temp_ox_id = ntohl(*(tach_header + 6)) >> 16;
- /* We care about the SCSI writes only. Those are the wicked ones
- * that need an additional set of buffers.
- */
- while(temp_ox_id <= MAX_SCSI_XID) {
- update_tachyon_header_indx(fi);
- if (fi->q.tachyon_header_indx == initial_indx) {
- /* Should never happen.
- */
- T_MSG("No free Tachyon headers available");
- reset_tachyon(fi, SOFTWARE_RESET);
- return 1;
- }
- tach_header = fi->q.ptr_tachyon_header[fi->q.tachyon_header_indx];
- temp_ox_id = ntohl(*(tach_header + 6)) >> 16;
- }
- return 0;
- }
- static int get_free_EDB(struct fc_info *fi)
- {
- unsigned int initial_indx = fi->q.edb_buffer_indx;
- /* Check if the EDB is in use.
- * We could have an outstanding SCSI Write command.
- * We should find a free slot as we can queue a
- * maximum of 32 SCSI commands only.
- */
- while (fi->q.free_edb_list[fi->q.edb_buffer_indx] != EDB_FREE) {
- update_EDB_indx(fi);
- if (fi->q.edb_buffer_indx == initial_indx) {
- T_MSG("No free EDB buffers avaliable")
- reset_tachyon(fi, SOFTWARE_RESET);
- return 1;
- }
- }
- return 0;
- }
- static int validate_login(struct fc_info *fi, u_int *base_ptr)
- {
- struct fc_node_info *q = fi->node_info_list;
- char n_port_name[PORT_NAME_LEN];
- char node_name[NODE_NAME_LEN];
- u_int s_id;
- ENTER("validate_login");
- /*index to Port Name in the payload. We need the 8 byte Port Name */
- memcpy(n_port_name, base_ptr + 10, PORT_NAME_LEN);
- memcpy(node_name, base_ptr + 12, NODE_NAME_LEN);
- s_id = ntohl(*(base_ptr + 3)) & 0x00FFFFFF;
-
- /* check if Fibre Channel IDs have changed */
- while(q != NULL) {
- if (memcmp(n_port_name, q->hw_addr, PORT_NAME_LEN) == 0) {
- if ((s_id != q->d_id) || (memcmp(node_name, q->node_name, NODE_NAME_LEN) != 0)) {
- DPRINTK1("Fibre Channel ID of Node has changed. Txing LOGO.");
- return 0;
- }
- q->login = LOGIN_COMPLETED;
- #if DEBUG_5526_2
- display_cache(fi);
- #endif
- return 1;
- }
- q = q->next;
- }
- DPRINTK1("Port Name does not match. Txing LOGO.");
- return 0;
- LEAVE("validate_login");
- }
- static void add_to_address_cache(struct fc_info *fi, u_int *base_ptr)
- {
- int size = sizeof(struct fc_node_info);
- struct fc_node_info *p, *q = fi->node_info_list, *r = NULL;
- char n_port_name[PORT_NAME_LEN];
- u_int s_id;
- ENTER("add_to_address_cache");
- /*index to Port Name in the payload. We need the 8 byte Port Name */
- memcpy(n_port_name, base_ptr + 13, PORT_NAME_LEN);
- s_id = ntohl(*(base_ptr + 3)) & 0x00FFFFFF;
-
- /* check if info already exists */
- while(q != NULL) {
- if (memcmp(n_port_name, q->hw_addr, PORT_NAME_LEN) == 0) {
- if (s_id != q->d_id) {
- memcpy(&(q->c_of_s[0]), base_ptr + 17, 3 * sizeof(CLASS_OF_SERVICE));
- q->mtu = ntohl(*(base_ptr + 10)) & 0x00000FFF;
- q->d_id = s_id;
- memcpy(q->node_name, base_ptr + 15, NODE_NAME_LEN);
- }
- q->login = LOGIN_COMPLETED;
- q->scsi = FALSE;
- fi->num_nodes++;
- #if DEBUG_5526_2
- display_cache(fi);
- #endif
- return;
- }
- r = q;
- q = q->next;
- }
- p = (struct fc_node_info *)kmalloc(size, GFP_ATOMIC);
- if (p == NULL) {
- T_MSG("kmalloc failed in add_to_address_cache()");
- return;
- }
- memcpy(&(p->c_of_s[0]), base_ptr + 17, 3 * sizeof(CLASS_OF_SERVICE));
- p->mtu = ntohl(*(base_ptr + 10)) & 0x00000FFF;
- p->d_id = s_id;
- memcpy(p->hw_addr, base_ptr + 13, PORT_NAME_LEN);
- memcpy(p->node_name, base_ptr + 15, NODE_NAME_LEN);
- p->login = LOGIN_COMPLETED;
- p->scsi = FALSE;
- p->target_id = 0xFF;
- p->next = NULL;
- if (fi->node_info_list == NULL)
- fi->node_info_list = p;
- else
- r->next = p;
- fi->num_nodes++;
- #if DEBUG_5526_2
- display_cache(fi);
- #endif
- LEAVE("add_to_address_cache");
- return;
- }
- static void remove_from_address_cache(struct fc_info *fi, u_int *base_ptr, u_int cmnd_code)
- {
- struct fc_node_info *q = fi->node_info_list;
- u_int s_id;
- ENTER("remove_from_address_cache");
- s_id = ntohl(*(base_ptr + 3)) & 0x00FFFFFF;
- switch(cmnd_code) {
- case ELS_LOGO:
- /* check if info exists */
- while (q != NULL) {
- if (s_id == q->d_id) {
- if (q->login == LOGIN_COMPLETED)
- q->login = LOGIN_ATTEMPTED;
- if (fi->num_nodes > 0)
- fi->num_nodes--;
- #if DEBUG_5526_2
- display_cache(fi);
- #endif
- return;
- }
- q = q->next;
- }
- DPRINTK1("ELS_LOGO received from node 0x%x which is not logged-in", s_id);
- break;
- case ELS_RSCN:
- {
- int payload_len = ntohl(*(base_ptr + 8)) & 0xFF;
- int no_of_pages, i;
- u_char address_format;
- u_short received_ox_id = ntohl(*(base_ptr + 6)) >> 16;
- u_int node_id, mask, *page_ptr = base_ptr + 9;
- if ((payload_len < 4) || (payload_len > 256)) {
- DPRINTK1("RSCN with invalid payload length received");
- tx_ls_rjt(fi, s_id, received_ox_id, LOGICAL_ERR, RECV_FIELD_SIZE);
- return;
- }
- /* Page_size includes the Command Code */
- no_of_pages = (payload_len / 4) - 1;
- for (i = 0; i < no_of_pages; i++) {
- address_format = ntohl(*page_ptr) >> 24;
- node_id = ntohl(*page_ptr) & 0x00FFFFFF;
- switch(address_format) {
- case PORT_ADDRESS_FORMAT:
- rscn_handler(fi, node_id);
- break;
- case AREA_ADDRESS_FORMAT:
- case DOMAIN_ADDRESS_FORMAT:
- if (address_format == AREA_ADDRESS_FORMAT)
- mask = 0xFFFF00;
- else
- mask = 0xFF0000;
- while(q != NULL) {
- if ((q->d_id & mask) == (node_id & mask))
- rscn_handler(fi, q->d_id);
- q = q->next;
- }
- /* There might be some new nodes to be
- * discovered. But, some of the earlier
- * requests as a result of the RSCN might be
- * in progress. We dont want to duplicate that
- * effort. So letz call SCR after a lag.
- */
- fi->explore_timer.function = scr_timer;
- fi->explore_timer.data = (unsigned long)fi;
- fi->explore_timer.expires = RUN_AT((no_of_pages*3*HZ)/100);
- init_timer(&fi->explore_timer);
- add_timer(&fi->explore_timer);
- break;
- default:
- T_MSG("RSCN with invalid address format received");
- tx_ls_rjt(fi, s_id, received_ox_id, LOGICAL_ERR, NO_EXPLN);
- }
- page_ptr += 1;
- } /* end of for loop */
- } /* end of case RSCN: */
- break;
- }
- #if DEBUG_5526_2
- display_cache(fi);
- #endif
- LEAVE("remove_from_address_cache");
- }
- static void rscn_handler(struct fc_info *fi, u_int node_id)
- {
- struct fc_node_info *q = fi->node_info_list;
- int login_state = sid_logged_in(fi, node_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN)) {
- while(q != NULL) {
- if (q->d_id == node_id) {
- q->login = LOGIN_ATTEMPTED;
- if (fi->num_nodes > 0)
- fi->num_nodes--;
- break;
- }
- else
- q = q->next;
- }
- }
- else
- if (login_state == NODE_LOGGED_OUT)
- tx_adisc(fi, ELS_ADISC, node_id, OX_ID_FIRST_SEQUENCE);
- else
- if (login_state == NODE_LOGGED_OUT)
- tx_logi(fi, ELS_PLOGI, node_id);
- }
- static void scr_timer(unsigned long data)
- {
- struct fc_info *fi = (struct fc_info *)data;
- del_timer(&fi->explore_timer);
- tx_name_server_req(fi, FCS_GP_ID4);
- }
- static int sid_logged_in(struct fc_info *fi, u_int s_id)
- {
- struct fc_node_info *temp = fi->node_info_list;
- while(temp != NULL)
- if ((temp->d_id == s_id) && (temp->login == LOGIN_COMPLETED)) {
- if (temp->scsi != FALSE)
- return NODE_PROCESS_LOGGED_IN;
- else
- return NODE_LOGGED_IN;
- }
- else
- if ((temp->d_id == s_id) && (temp->login != LOGIN_COMPLETED))
- return NODE_LOGGED_OUT;
- else
- temp = temp->next;
- return NODE_NOT_PRESENT;
- }
- static void mark_scsi_sid(struct fc_info *fi, u_int *buff_addr, u_char action)
- {
- struct fc_node_info *temp = fi->node_info_list;
- u_int s_id;
- u_int service_params;
- s_id = ntohl(*(buff_addr + 3)) & 0x00FFFFFF;
- service_params = ntohl(*(buff_addr + 12)) & 0x000000F0;
- while(temp != NULL)
- if ((temp->d_id == s_id) && (temp->login == LOGIN_COMPLETED)) {
- if (action == DELETE_ENTRY) {
- temp->scsi = FALSE;
- #if DEBUG_5526_2
- display_cache(fi);
- #endif
- return;
- }
- /* Check if it is a SCSI Target */
- if (!(service_params & TARGET_FUNC)) {
- temp->scsi = INITIATOR;
- #if DEBUG_5526_2
- display_cache(fi);
- #endif
- return;
- }
- temp->scsi = TARGET;
- /* This helps to maintain the target_id no matter what your
- * Fibre Channel ID is.
- */
- if (temp->target_id == 0xFF) {
- if (fi->g.no_of_targets <= MAX_SCSI_TARGETS)
- temp->target_id = fi->g.no_of_targets++;
- else
- T_MSG("MAX TARGETS reached!");
- }
- else
- DPRINTK1("Target_id %d already present", temp->target_id);
- #if DEBUG_5526_2
- display_cache(fi);
- #endif
- return;
- }
- else
- temp = temp->next;
- return;
- }
- static int node_logged_in_prev(struct fc_info *fi, u_int *buff_addr)
- {
- struct fc_node_info *temp;
- u_char *data = (u_char *)buff_addr;
- u_int s_id;
- char node_name[NODE_NAME_LEN];
- s_id = ntohl(*(buff_addr + 3)) & 0x00FFFFFF;
- memcpy(node_name, buff_addr + 12, NODE_NAME_LEN);
- /* point to port_name in the ADISC payload */
- data += 10 * 4;
- /* point to last 6 bytes of port_name */
- data += 2;
- temp = look_up_cache(fi, data);
- if (temp != NULL) {
- if ((temp->d_id == s_id) && (memcmp(node_name, temp->node_name, NODE_NAME_LEN) == 0)) {
- temp->login = LOGIN_COMPLETED;
- #if DEBUG_5526_2
- display_cache(fi);
- #endif
- return TRUE;
- }
- }
- return FALSE;
- }
- static struct fc_node_info *look_up_cache(struct fc_info *fi, char *data)
- {
- struct fc_node_info *temp_list = fi->node_info_list, *q;
- u_char n_port_name[FC_ALEN], temp_addr[FC_ALEN];
- ENTER("look_up_cache");
- memcpy(n_port_name, data, FC_ALEN);
- while(temp_list) {
- if (memcmp(n_port_name, &(temp_list->hw_addr[2]), FC_ALEN) == 0)
- return temp_list;
- else
- temp_list = temp_list->next;
- }
-
- /* Broadcast IP ?
- */
- temp_addr[0] = temp_addr[1] = temp_addr[2] = 0xFF;
- temp_addr[3] = temp_addr[4] = temp_addr[5] = 0xFF;
- if (memcmp(n_port_name, temp_addr, FC_ALEN) == 0) {
- q = (struct fc_node_info *)kmalloc(sizeof(struct fc_node_info), GFP_ATOMIC);
- if (q == NULL) {
- T_MSG("kmalloc failed in look_up_cache()");
- return NULL;
- }
- q->d_id = BROADCAST;
- return q;
- }
- LEAVE("look_up_cache");
- return NULL;
- }
- static int display_cache(struct fc_info *fi)
- {
- struct fc_node_info *q = fi->node_info_list;
- #if DEBUG_5526_2
- struct ox_id_els_map *temp_ox_id_list = fi->ox_id_list;
- #endif
- int count = 0, j;
- printk("nFibre Channel Node Information for %sn", fi->name);
- printk("My FC_ID = %x, My WWN = %x %x, ", fi->g.my_id, fi->g.my_node_name_high, fi->g.my_node_name_low);
- if (fi->g.ptp_up == TRUE)
- printk("Port_Type = N_Portn");
- if (fi->g.loop_up == TRUE)
- printk("Port_Type = L_Portn");
- while(q != NULL) {
- printk("WWN = ");
- for (j = 0; j < PORT_NAME_LEN; j++)
- printk("%x ", q->hw_addr[j]);
- printk("FC_ID = %x, ", q->d_id);
- printk("Login = ");
- if (q->login == LOGIN_COMPLETED)
- printk("ON ");
- else
- printk("OFF ");
- if (q->scsi == TARGET)
- printk("Target_ID = %d ", q->target_id);
- printk("n");
- q = q->next;
- count++;
- }
- #if DEBUG_5526_2
- printk("OX_ID -> ELS Mapn");
- while(temp_ox_id_list) {
- printk("ox_id = %x, ELS = %xn", temp_ox_id_list->ox_id, temp_ox_id_list->els);
- temp_ox_id_list = temp_ox_id_list->next;
- }
- #endif
- return 0;
- }
- static struct net_device_stats * iph5526_get_stats(struct net_device *dev)
- {
- struct fc_info *fi = (struct fc_info*)dev->priv;
- return (struct net_device_stats *) &fi->fc_stats;
- }
- /* SCSI stuff starts here */
- int iph5526_detect(Scsi_Host_Template *tmpt)
- {
- struct Scsi_Host *host = NULL;
- struct iph5526_hostdata *hostdata;
- struct fc_info *fi = NULL;
- int no_of_hosts = 0, timeout, i, j, count = 0;
- u_int pci_maddr = 0;
- struct pci_dev *pdev = NULL;
- tmpt->proc_name = "iph5526";
- if (pci_present() == 0) {
- printk("iph5526: PCI not presentn");
- return 0;
- }
- for (i = 0; i <= MAX_FC_CARDS; i++)
- fc[i] = NULL;
- for (i = 0; i < clone_list[i].vendor_id != 0; i++)
- while ((pdev = pci_find_device(clone_list[i].vendor_id, clone_list[i].device_id, pdev))) {
- unsigned short pci_command;
- if (pci_enable_device(pdev))
- continue;
- if (count < MAX_FC_CARDS) {
- fc[count] = kmalloc(sizeof(struct fc_info), GFP_ATOMIC);
- if (fc[count] == NULL) {
- printk("iph5526.c: Unable to register card # %dn", count + 1);
- return no_of_hosts;
- }
- memset(fc[count], 0, sizeof(struct fc_info));
- }
- else {
- printk("iph5526.c: Maximum Number of cards reached.n");
- return no_of_hosts;
- }
-
- fi = fc[count];
- sprintf(fi->name, "fc%d", count);
- host = scsi_register(tmpt, sizeof(struct iph5526_hostdata));
- if(host==NULL)
- return no_of_hosts;
-
- hostdata = (struct iph5526_hostdata *)host->hostdata;
- memset(hostdata, 0 , sizeof(struct iph5526_hostdata));
- for (j = 0; j < MAX_SCSI_TARGETS; j++)
- hostdata->tag_ages[j] = jiffies;
- hostdata->fi = fi;
- fi->host = host;
- //host->max_id = MAX_SCSI_TARGETS;
- host->max_id = 5;
- host->hostt->use_new_eh_code = 1;
- host->this_id = tmpt->this_id;
- pci_maddr = pci_resource_start(pdev, 0);
- if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
- printk("iph5526.c : Cannot find proper PCI device base address.n");
- scsi_unregister(host);
- kfree(fc[count]);
- fc[count] = NULL;
- continue;
- }
-
- DPRINTK("pci_maddr = %x", pci_maddr);
- pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
-
- pci_irq_line = pdev->irq;
- printk("iph5526.c: PCI BIOS reports %s at i/o %#x, irq %d.n", clone_list[i].name, pci_maddr, pci_irq_line);
- fi->g.mem_base = ioremap(pci_maddr & PAGE_MASK, 1024);
-
- /* We use Memory Mapped IO. The initial space contains the
- * PCI Configuration registers followed by the (i) chip
- * registers followed by the Tachyon registers.
- */
- /* Thatz where (i)chip maps Tachyon Address Space.
- */
- fi->g.tachyon_base = (u_long)fi->g.mem_base + TACHYON_OFFSET + ( pci_maddr & ~PAGE_MASK );
- DPRINTK("fi->g.tachyon_base = %x", (u_int)fi->g.tachyon_base);
- if (fi->g.mem_base == NULL) {
- printk("iph5526.c : ioremap failed!!!n");
- scsi_unregister(host);
- kfree(fc[count]);
- fc[count] = NULL;
- continue;
- }
- DPRINTK("IRQ1 = %dn", pci_irq_line);
- printk(version);
- fi->base_addr = (long) pdev;
- if (pci_irq_line) {
- int irqval = 0;
- /* Found it, get IRQ.
- */
- irqval = request_irq(pci_irq_line, &tachyon_interrupt, pci_irq_line ? SA_SHIRQ : 0, fi->name, host);
- if (irqval) {
- printk("iph5526.c : Unable to get IRQ %d (irqval = %d).n", pci_irq_line, irqval);
- scsi_unregister(host);
- kfree(fc[count]);
- fc[count] = NULL;
- continue;
- }
- host->irq = fi->irq = pci_irq_line;
- pci_irq_line = 0;
- fi->clone_id = clone_list[i].vendor_id;
- }
- if (!initialize_register_pointers(fi) || !tachyon_init(fi)) {
- printk("iph5526.c: TACHYON initialization failed for card # %d!!!n", count + 1);
- free_irq(host->irq, host);
- scsi_unregister(host);
- if (fi)
- clean_up_memory(fi);
- kfree(fc[count]);
- fc[count] = NULL;
- break;
- }
- DPRINTK1("Fibre Channel card initialized");
- /* Wait for the Link to come up and the login process
- * to complete.
- */
- for(timeout = jiffies + 10*HZ; (timeout > jiffies) && ((fi->g.link_up == FALSE) || (fi->g.port_discovery == TRUE) || (fi->g.explore_fabric == TRUE) || (fi->g.perform_adisc == TRUE));)
- barrier();
-
- count++;
- no_of_hosts++;
- }
- DPRINTK1("no_of_hosts = %d",no_of_hosts);
-
- /* This is to make sure that the ACC to the PRLI comes in
- * for the last ALPA.
- */
- mdelay(1000); /* Ugly! Let the Gods forgive me */
- DPRINTK1("leaving iph5526_detectn");
- return no_of_hosts;
- }
- int iph5526_biosparam(Disk * disk, kdev_t n, int ip[])
- {
- int size = disk->capacity;
- ip[0] = 64;
- ip[1] = 32;
- ip[2] = size >> 11;
- if (ip[2] > 1024) {
- ip[0] = 255;
- ip[1] = 63;
- ip[2] = size / (ip[0] * ip[1]);
- }
- return 0;
- }
- int iph5526_queuecommand(Scsi_Cmnd *Cmnd, void (*done) (Scsi_Cmnd *))
- {
- int int_required = 0;
- u_int r_ctl = FC4_DEVICE_DATA | UNSOLICITED_COMMAND;
- u_int type = TYPE_FCP | SEQUENCE_INITIATIVE;
- u_int frame_class = Cmnd->target;
- u_short ox_id = OX_ID_FIRST_SEQUENCE;
- struct Scsi_Host *host = Cmnd->host;
- struct iph5526_hostdata *hostdata = (struct iph5526_hostdata*)host->hostdata;
- struct fc_info *fi = hostdata->fi;
- struct fc_node_info *q;
- u_long flags;
- ENTER("iph5526_queuecommand");
- spin_lock_irqsave(&fi->fc_lock, flags);
- Cmnd->scsi_done = done;
- if (Cmnd->device->tagged_supported) {
- switch(Cmnd->tag) {
- case SIMPLE_QUEUE_TAG:
- hostdata->cmnd.fcp_cntl = FCP_CNTL_QTYPE_SIMPLE;
- break;
- case HEAD_OF_QUEUE_TAG:
- hostdata->cmnd.fcp_cntl = FCP_CNTL_QTYPE_HEAD_OF_Q;
- break;
- case ORDERED_QUEUE_TAG:
- hostdata->cmnd.fcp_cntl = FCP_CNTL_QTYPE_ORDERED;
- break;
- default:
- if ((jiffies - hostdata->tag_ages[Cmnd->target]) > (5 * HZ)) {
- hostdata->cmnd.fcp_cntl = FCP_CNTL_QTYPE_ORDERED;
- hostdata->tag_ages[Cmnd->target] = jiffies;
- }
- else
- hostdata->cmnd.fcp_cntl = FCP_CNTL_QTYPE_SIMPLE;
- break;
- }
- }
- /*else
- hostdata->cmnd.fcp_cntl = FCP_CNTL_QTYPE_UNTAGGED;
- */
- hostdata->cmnd.fcp_addr[3] = 0;
- hostdata->cmnd.fcp_addr[2] = 0;
- hostdata->cmnd.fcp_addr[1] = 0;
- hostdata->cmnd.fcp_addr[0] = htons(Cmnd->lun);
- memcpy(&hostdata->cmnd.fcp_cdb, Cmnd->cmnd, Cmnd->cmd_len);
- hostdata->cmnd.fcp_data_len = htonl(Cmnd->request_bufflen);
- /* Get an used OX_ID. We could have pending commands.
- */
- if (get_scsi_oxid(fi)) {
- spin_unlock_irqrestore(&fi->fc_lock, flags);
- return 1;
- }
- fi->q.free_scsi_oxid[fi->g.scsi_oxid] = OXID_INUSE;
- /* Maintain a handler so that we can associate the done() function
- * on completion of the SCSI command.
- */
- hostdata->cmnd_handler[fi->g.scsi_oxid] = Cmnd;
- switch(Cmnd->cmnd[0]) {
- case WRITE_6:
- case WRITE_10:
- case WRITE_12:
- fi->g.type_of_frame = FC_SCSI_WRITE;
- hostdata->cmnd.fcp_cntl = htonl(FCP_CNTL_WRITE | hostdata->cmnd.fcp_cntl);
- break;
- default:
- fi->g.type_of_frame = FC_SCSI_READ;
- hostdata->cmnd.fcp_cntl = htonl(FCP_CNTL_READ | hostdata->cmnd.fcp_cntl);
- }
-
- memcpy(fi->q.ptr_fcp_cmnd[fi->q.fcp_cmnd_indx], &(hostdata->cmnd), sizeof(fcp_cmd));
-
- q = resolve_target(fi, Cmnd->target);
- if (q == NULL) {
- u_int bad_id = fi->g.my_ddaa | 0xFE;
- /* We transmit to an non-existant AL_PA so that the "done"
- * function can be called while receiving the interrupt
- * due to a Timeout for a bad AL_PA. In a PTP configuration,
- * the int_required field is set, since there is no notion
- * of AL_PAs. This approach sucks, but works alright!
- */
- if (fi->g.ptp_up == TRUE)
- int_required = 1;
- tx_exchange(fi, (char *)(&(hostdata->cmnd)), sizeof(fcp_cmd), r_ctl, type, bad_id, fi->g.my_mtu, int_required, ox_id, FC_SCSI_BAD_TARGET);
- spin_unlock_irqrestore(&fi->fc_lock, flags);
- DPRINTK1("Target ID %x not present", Cmnd->target);
- return 0;
- }
- if (q->login == LOGIN_COMPLETED) {
- if (add_to_sest(fi, Cmnd, q)) {
- DPRINTK1("add_to_sest() failed.");
- spin_unlock_irqrestore(&fi->fc_lock, flags);
- return 0;
- }
- tx_exchange(fi, (char *)(fi->q.ptr_fcp_cmnd[fi->q.fcp_cmnd_indx]), sizeof(fcp_cmd), r_ctl, type, q->d_id, q->mtu, int_required, ox_id, frame_class << 16);
- update_FCP_CMND_indx(fi);
- }
- spin_unlock_irqrestore(&fi->fc_lock, flags);
- /* If q != NULL, then we have a SCSI Target.
- * If q->login != LOGIN_COMPLETED, then that device could be
- * offline temporarily. So we let the command to time-out.
- */
- LEAVE("iph5526_queuecommand");
- return 0;
- }
- int iph5526_abort(Scsi_Cmnd *Cmnd)
- {
- struct Scsi_Host *host = Cmnd->host;
- struct iph5526_hostdata *hostdata = (struct iph5526_hostdata *)host->hostdata;
- struct fc_info *fi = hostdata->fi;
- struct fc_node_info *q;
- u_int r_ctl = FC4_DEVICE_DATA | UNSOLICITED_COMMAND;
- u_int type = TYPE_FCP | SEQUENCE_INITIATIVE;
- u_short ox_id = OX_ID_FIRST_SEQUENCE;
- int int_required = 1, i, abort_status = FALSE;
- u_long flags;
-
- ENTER("iph5526_abort");
-
- spin_lock_irqsave(&fi->fc_lock, flags);
-
- q = resolve_target(fi, Cmnd->target);
- if (q == NULL) {
- u_int bad_id = fi->g.my_ddaa | 0xFE;
- /* This should not happen as we should always be able to
- * resolve a target id. But, jus in case...
- * We transmit to an non-existant AL_PA so that the done
- * function can be called while receiving the interrupt
- * for a bad AL_PA.
- */
- DPRINTK1("Unresolved Target ID!");
- tx_exchange(fi, (char *)(&(hostdata->cmnd)), sizeof(fcp_cmd), r_ctl, type, bad_id, fi->g.my_mtu, int_required, ox_id, FC_SCSI_BAD_TARGET);
- DPRINTK1("Target ID %x not present", Cmnd->target);
- spin_unlock_irqrestore(&fi->fc_lock, flags);
- return FAILED;
- }
- /* If q != NULL, then we have a SCSI Target. If
- * q->login != LOGIN_COMPLETED, then that device could
- * be offline temporarily. So we let the command to time-out.
- */
- /* Get the OX_ID for the Command to be aborted.
- */
- for (i = 0; i <= MAX_SCSI_XID; i++) {
- if (hostdata->cmnd_handler[i] == Cmnd) {
- hostdata->cmnd_handler[i] = NULL;
- ox_id = i;
- break;
- }
- }
- if (i > MAX_SCSI_XID) {
- T_MSG("Command could not be resolved to OX_ID");
- spin_unlock_irqrestore(&fi->fc_lock, flags);
- return FAILED;
- }
- switch(Cmnd->cmnd[0]) {
- case WRITE_6:
- case WRITE_10:
- case WRITE_12:
- break;
- default:
- ox_id |= SCSI_READ_BIT;
- }
- abort_status = abort_exchange(fi, ox_id);
-
- if ((q->login == LOGIN_COMPLETED) && (abort_status == TRUE)) {
- /* Then, transmit an ABTS to the target. The rest
- * is done when the BA_ACC is received for the ABTS.
- */
- tx_abts(fi, q->d_id, ox_id);
- }
- else {
- u_int STE_bit;
- u_short x_id;
- /* Invalidate resources for that Exchange.
- */
- x_id = ox_id & MAX_SCSI_XID;
- STE_bit = ntohl(*fi->q.ptr_sest[x_id]);
- if (STE_bit & SEST_V) {
- *(fi->q.ptr_sest[x_id]) &= htonl(SEST_INV);
- invalidate_SEST_entry(fi, ox_id);
- }
- }
- LEAVE("iph5526_abort");
- spin_unlock_irqrestore(&fi->fc_lock, flags);
- return SUCCESS;
- }
- static int abort_exchange(struct fc_info *fi, u_short ox_id)
- {
- u_short x_id;
- volatile u_int flush_SEST, STE_bit;
- x_id = ox_id & MAX_SCSI_XID;
- DPRINTK1("Aborting Exchange %x", ox_id);
- STE_bit = ntohl(*fi->q.ptr_sest[x_id]);
- /* Is the Exchange still active?.
- */
- if (STE_bit & SEST_V) {
- if (ox_id & SCSI_READ_BIT) {
- /* If the Exchange to be aborted is Inbound,
- * Flush the SEST Entry from Tachyon's Cache.
- */
- *(fi->q.ptr_sest[x_id]) &= htonl(SEST_INV);
- flush_tachyon_cache(fi, ox_id);
- flush_SEST = readl(fi->t_r.ptr_tach_flush_oxid_reg);
- while ((flush_SEST & 0x80000000) != 0)
- flush_SEST = readl(fi->t_r.ptr_tach_flush_oxid_reg);
- STE_bit = ntohl(*fi->q.ptr_sest[x_id]);
- while ((STE_bit & 0x80000000) != 0)
- STE_bit = ntohl(*fi->q.ptr_sest[x_id]);
- flush_SEST = readl(fi->t_r.ptr_tach_flush_oxid_reg);
- invalidate_SEST_entry(fi, ox_id);
- }
- else {
- int i;
- u_int *ptr_edb;
- /* For In-Order Reassembly, the following is done:
- * First, write zero as the buffer length in the EDB.
- */
- ptr_edb = bus_to_virt(ntohl(*(fi->q.ptr_sest[x_id] + 7)));
- for (i = 0; i < EDB_LEN; i++)
- if (fi->q.ptr_edb[i] == ptr_edb)
- break;
- if (i < EDB_LEN)
- *ptr_edb = *ptr_edb & 0x0000FFFF;
- else
- T_MSG("EDB not found while clearing in abort_exchange()");
- }
- DPRINTK1("Exchange %x invalidated", ox_id);
- return TRUE;
- }
- else {
- DPRINTK1("SEST Entry for exchange %x not valid", ox_id);
- return FALSE;
- }
- }
- static void flush_tachyon_cache(struct fc_info *fi, u_short ox_id)
- {
- volatile u_int tachyon_status;
- if (fi->g.loop_up == TRUE) {
- writel(HOST_CONTROL, fi->t_r.ptr_fm_control_reg);
- /* Make sure that the Inbound FIFO is empty.
- */
- do {
- tachyon_status = readl(fi->t_r.ptr_tach_status_reg);
- udelay(200);
- }while ((tachyon_status & RECEIVE_FIFO_EMPTY) == 0);
- /* Ok. Go ahead and flushhhhhhhhh!
- */
- writel(0x80000000 | ox_id, fi->t_r.ptr_tach_flush_oxid_reg);
- writel(EXIT_HOST_CONTROL, fi->t_r.ptr_fm_control_reg);
- return;
- }
- if (fi->g.ptp_up == TRUE) {
- take_tachyon_offline(fi);
- /* Make sure that the Inbound FIFO is empty.
- */
- do {
- tachyon_status = readl(fi->t_r.ptr_tach_status_reg);
- udelay(200);
- }while ((tachyon_status & RECEIVE_FIFO_EMPTY) == 0);
- writel(0x80000000 | ox_id, fi->t_r.ptr_tach_flush_oxid_reg);
- /* Write the Initialize command to the FM Control reg.
- */
- fi->g.n_port_try = TRUE;
- DPRINTK1("In abort_exchange, TACHYON initializing as N_Port...n");
- writel(INITIALIZE, fi->t_r.ptr_fm_control_reg);
- }
- }
- static struct fc_node_info *resolve_target(struct fc_info *fi, u_char target)
- {
- struct fc_node_info *temp = fi->node_info_list;
- while(temp != NULL)
- if (temp->target_id == target) {
- if ((temp->scsi == TARGET) && (temp->login == LOGIN_COMPLETED))
- return temp;
- else {
- if (temp->login != LOGIN_COMPLETED) {
- /* The Target is not currently logged in.
- * It could be a Target on the Local Loop or
- * on a Remote Loop connected through a switch.
- * In either case, we will know whenever the Target
- * comes On-Line again. We let the command to
- * time-out so that it gets retried.
- */
- T_MSG("Target %d not logged in.", temp->target_id);
- tx_logi(fi, ELS_PLOGI, temp->d_id);
- return temp;
- }
- else {
- if (temp->scsi != TARGET) {
- /* For some reason, we did not get a response to
- * PRLI. Letz try it again...
- */
- DPRINTK1("Node not PRLIied. Txing PRLI...");
- tx_prli(fi, ELS_PRLI, temp->d_id, OX_ID_FIRST_SEQUENCE);
- }
- }
- return temp;
- }
- }
- else
- temp = temp->next;
- return NULL;
- }
- static int add_to_sest(struct fc_info *fi, Scsi_Cmnd *Cmnd, struct fc_node_info *ni)
- {
- /* we have at least 1 buffer, the terminator */
- int no_of_sdb_buffers = 1, i;
- int no_of_edb_buffers = 0;
- u_int *req_buffer = (u_int *)Cmnd->request_buffer;
- u_int *ptr_sdb = NULL;
- struct scatterlist *sl1, *sl2 = NULL;
- int no_of_sg = 0;
- switch(fi->g.type_of_frame) {
- case FC_SCSI_READ:
- fi->g.inb_sest_entry.flags_and_byte_offset = htonl(INB_SEST_VED);
- fi->g.inb_sest_entry.byte_count = 0;
- fi->g.inb_sest_entry.no_of_recvd_frames = 0;
- fi->g.inb_sest_entry.no_of_expected_frames = 0;
- fi->g.inb_sest_entry.last_fctl = 0;
- if (Cmnd->use_sg) {
- no_of_sg = Cmnd->use_sg;
- sl1 = sl2 = (struct scatterlist *)Cmnd->request_buffer;
- for (i = 0; i < no_of_sg; i++) {
- no_of_sdb_buffers += sl1->length / SEST_BUFFER_SIZE;
- if (sl1->length % SEST_BUFFER_SIZE)
- no_of_sdb_buffers++;
- sl1++;
- }
- }
- else {
- no_of_sdb_buffers += Cmnd->request_bufflen / SEST_BUFFER_SIZE;
- if (Cmnd->request_bufflen % SEST_BUFFER_SIZE)
- no_of_sdb_buffers++;
- } /* if !use_sg */
- /* We are working with the premise that at the max we would
- * get a scatter-gather buffer containing 63 buffers
- * of size 1024 bytes each. Is it a _bad_ assumption?
- */
- if (no_of_sdb_buffers > 512) {
- T_MSG("Number of SDB buffers needed = %d", no_of_sdb_buffers);
- T_MSG("Disable Scatter-Gather!!!");
- return 1;
- }
-
- /* Store it in the sdb_table so that we can retrieve that
- * free up the memory when the Read Command completes.
- */
- if (get_free_SDB(fi))
- return 1;
- ptr_sdb = fi->q.ptr_sdb_slot[fi->q.sdb_indx];
- fi->q.sdb_slot_status[fi->q.sdb_indx] = SDB_BUSY;
- fi->g.inb_sest_entry.sdb_address = htonl(virt_to_bus(ptr_sdb));
- if (Cmnd->use_sg) {
- int count = 0, j;
- for(i = 0; i < no_of_sg; i++) {
- char *addr_ptr = sl2->address;
- count = sl2->length / SEST_BUFFER_SIZE;
- if (sl2->length % SEST_BUFFER_SIZE)
- count++;
- for (j = 0; j < count; j++) {
- *(ptr_sdb) = htonl(virt_to_bus(addr_ptr));
- addr_ptr += SEST_BUFFER_SIZE;
- ptr_sdb++;
- }
- count = 0;
- sl2++;
- }
- }
- else {
- for (i = 0; i < no_of_sdb_buffers - 1; i++) {
- *(ptr_sdb) = htonl(virt_to_bus(req_buffer));
- req_buffer += SEST_BUFFER_SIZE/4;
- ptr_sdb++;
- }
- }
- *(ptr_sdb) = htonl(0x1); /* Terminator */
-
- /* The scratch pad is used to hold the index into the SDB.
- */
- fi->g.inb_sest_entry.scratch_pad = fi->q.sdb_indx;
- fi->g.inb_sest_entry.expected_ro = 0;
- fi->g.inb_sest_entry.buffer_index = 0;
- fi->g.inb_sest_entry.buffer_offset = 0;
- memcpy(fi->q.ptr_sest[fi->g.scsi_oxid], &fi->g.inb_sest_entry, sizeof(INB_SEST_ENTRY));
- break;
- case FC_SCSI_WRITE:
- fi->g.outb_sest_entry.flags_and_did = htonl(OUTB_SEST_VED | ni->d_id);
- fi->g.outb_sest_entry.max_frame_len = htons(ni->mtu << 4);
- fi->g.outb_sest_entry.cntl = htons(ODB_CLASS_3 | ODB_EE_CREDIT | ODB_NO_INT | ODB_NO_COMP);
- fi->g.outb_sest_entry.total_seq_length = INV_SEQ_LEN;
- fi->g.outb_sest_entry.link = htons(OUTB_SEST_LINK);
- fi->g.outb_sest_entry.transaction_id = htonl(fi->g.scsi_oxid);
- fi->g.outb_sest_entry.seq_id = fi->g.seq_id;
- fi->g.outb_sest_entry.reserved = 0x0;
- fi->g.outb_sest_entry.header_length = htons(TACHYON_HEADER_LEN);
-
- {
- u_char df_ctl = 0;
- u_short rx_id = RX_ID_FIRST_SEQUENCE;
- u_int r_ctl = FC4_DEVICE_DATA | SOLICITED_DATA;
- u_int type = TYPE_FCP | SEQUENCE_INITIATIVE;
- /* Multi Frame Sequence ? If yes, set RO bit.
- */
- if (Cmnd->request_bufflen > ni->mtu)
- type |= RELATIVE_OFF_PRESENT;
- build_tachyon_header(fi, fi->g.my_id, r_ctl, ni->d_id, type, fi->g.seq_id, df_ctl, fi->g.scsi_oxid, rx_id, NULL);
- if (get_free_header(fi) || get_free_EDB(fi))
- return 1;
- memcpy(fi->q.ptr_tachyon_header[fi->q.tachyon_header_indx], &(fi->g.tach_header), TACHYON_HEADER_LEN);
- fi->g.outb_sest_entry.header_address = htonl(virt_to_bus(fi->q.ptr_tachyon_header[fi->q.tachyon_header_indx]));
- update_tachyon_header_indx(fi);
- }
- if (Cmnd->use_sg) {
- no_of_sg = Cmnd->use_sg;
- sl1 = sl2 = (struct scatterlist *)Cmnd->request_buffer;
- for (i = 0; i < no_of_sg; i++) {
- no_of_edb_buffers += sl1->length / SEST_BUFFER_SIZE;
- if (sl1->length % SEST_BUFFER_SIZE)
- no_of_edb_buffers++;
- sl1++;
- }
- }
- else {
- no_of_edb_buffers += Cmnd->request_bufflen / SEST_BUFFER_SIZE;
- if (Cmnd->request_bufflen % SEST_BUFFER_SIZE)
- no_of_edb_buffers++;
- } /* if !use_sg */
- /* We need "no_of_edb_buffers" _contiguous_ EDBs
- * that are FREE. Check for that first.
- */
- for (i = 0; i < no_of_edb_buffers; i++) {
- int j;
- if ((fi->q.edb_buffer_indx + no_of_edb_buffers) >= EDB_LEN)
- fi->q.edb_buffer_indx = 0;
- if (fi->q.free_edb_list[fi->q.edb_buffer_indx + i] != EDB_FREE) {
- for (j = 0; j < i; j++)
- update_EDB_indx(fi);
- if (get_free_EDB(fi))
- return 1;
- i = 0;
- }
- }
- /* We got enuff FREE EDBs.
- */
- if (Cmnd->use_sg) {
- fi->g.outb_sest_entry.edb_address = htonl(virt_to_bus(fi->q.ptr_edb[fi->q.edb_buffer_indx]));
- sl1 = (struct scatterlist *)Cmnd->request_buffer;
- for(i = 0; i < no_of_sg; i++) {
- int count = 0, j;
- count = sl1->length / SEST_BUFFER_SIZE;
- for (j = 0; j < count; j++) {
- build_EDB(fi, (char *)sl1->address, 0, SEST_BUFFER_SIZE);
- memcpy(fi->q.ptr_edb[fi->q.edb_buffer_indx], &(fi->g.edb), sizeof(EDB));
- /* Mark this EDB as being in use */
- fi->q.free_edb_list[fi->q.edb_buffer_indx] = EDB_BUSY;
- /* We have already made sure that we have enuff
- * free EDBs that are contiguous. So this is
- * safe.
- */
- update_EDB_indx(fi);
- sl1->address += SEST_BUFFER_SIZE;
- }
- /* Just in case itz not a multiple of
- * SEST_BUFFER_SIZE bytes.
- */
- if (sl1->length % SEST_BUFFER_SIZE) {
- build_EDB(fi, (char *)sl1->address, 0, sl1->length % SEST_BUFFER_SIZE);
- memcpy(fi->q.ptr_edb[fi->q.edb_buffer_indx], &(fi->g.edb), sizeof(EDB));
- fi->q.free_edb_list[fi->q.edb_buffer_indx] = EDB_BUSY;
- update_EDB_indx(fi);
- }
- sl1++;
- }
- /* The last EDB is special. It needs the "end bit" to
- * be set.
- */
- *(fi->q.ptr_edb[fi->q.edb_buffer_indx - 1] + 1) = *(fi->q.ptr_edb[fi->q.edb_buffer_indx - 1] + 1) | ntohs(EDB_END);
- }
- else {
- int count = 0, j;
- fi->g.outb_sest_entry.edb_address = htonl(virt_to_bus(fi->q.ptr_edb[fi->q.edb_buffer_indx]));
- count = Cmnd->request_bufflen / SEST_BUFFER_SIZE;
- for (j = 0; j < count; j++) {
- build_EDB(fi, (char *)req_buffer, 0, SEST_BUFFER_SIZE);
- memcpy(fi->q.ptr_edb[fi->q.edb_buffer_indx], &(fi->g.edb), sizeof(EDB));
- /* Mark this EDB as being in use */
- fi->q.free_edb_list[fi->q.edb_buffer_indx] = EDB_BUSY;
- /* We have already made sure that we have enuff
- * free EDBs that are contiguous. So this is
- * safe.
- */
- update_EDB_indx(fi);
- req_buffer += SEST_BUFFER_SIZE;
- }
- /* Just in case itz not a multiple of
- * SEST_BUFFER_SIZE bytes.
- */
- if (Cmnd->request_bufflen % SEST_BUFFER_SIZE) {
- build_EDB(fi, (char *)req_buffer, EDB_END, Cmnd->request_bufflen % SEST_BUFFER_SIZE);
- memcpy(fi->q.ptr_edb[fi->q.edb_buffer_indx], &(fi->g.edb), sizeof(EDB));
- fi->q.free_edb_list[fi->q.edb_buffer_indx] = EDB_BUSY;
- update_EDB_indx(fi);
- }
- else {
- /* Mark the last EDB as the "end edb".
- */
- *(fi->q.ptr_edb[fi->q.edb_buffer_indx - 1] + 1) = *(fi->q.ptr_edb[fi->q.edb_buffer_indx - 1] + 1) | htons(EDB_END);
- }
- }
- /* Finally we have something to send!.
- */
- memcpy(fi->q.ptr_sest[fi->g.scsi_oxid], &fi->g.outb_sest_entry, sizeof(OUTB_SEST_ENTRY));
- break;
- }
- return 0;
- }
- static void update_FCP_CMND_indx(struct fc_info *fi)
- {
- fi->q.fcp_cmnd_indx++;
- if (fi->q.fcp_cmnd_indx == NO_OF_FCP_CMNDS)
- fi->q.fcp_cmnd_indx = 0;
- }
- static int get_scsi_oxid(struct fc_info *fi)
- {
- u_short initial_oxid = fi->g.scsi_oxid;
- /* Check if the OX_ID is in use.
- * We could have an outstanding SCSI command.
- */
- while (fi->q.free_scsi_oxid[fi->g.scsi_oxid] != OXID_AVAILABLE) {
- update_scsi_oxid(fi);
- if (fi->g.scsi_oxid == initial_oxid) {
- T_MSG("No free OX_IDs avaliable")
- reset_tachyon(fi, SOFTWARE_RESET);
- return 1;
- }
- }
- return 0;
- }
- static void update_scsi_oxid(struct fc_info *fi)
- {
- fi->g.scsi_oxid++;
- if (fi->g.scsi_oxid == (MAX_SCSI_XID + 1))
- fi->g.scsi_oxid = 0;
- }
- static int get_free_SDB(struct fc_info *fi)
- {
- unsigned int initial_indx = fi->q.sdb_indx;
- /* Check if the SDB is in use.
- * We could have an outstanding SCSI Read command.
- * We should find a free slot as we can queue a
- * maximum of 32 SCSI commands only.
- */
- while (fi->q.sdb_slot_status[fi->q.sdb_indx] != SDB_FREE) {
- update_SDB_indx(fi);
- if (fi->q.sdb_indx == initial_indx) {
- T_MSG("No free SDB buffers avaliable")
- reset_tachyon(fi, SOFTWARE_RESET);
- return 1;
- }
- }
- return 0;
- }
- static void update_SDB_indx(struct fc_info *fi)
- {
- fi->q.sdb_indx++;
- if (fi->q.sdb_indx == NO_OF_SDB_ENTRIES)
- fi->q.sdb_indx = 0;
- }
- int iph5526_release(struct Scsi_Host *host)
- {
- struct iph5526_hostdata *hostdata = (struct iph5526_hostdata*)host->hostdata;
- struct fc_info *fi = hostdata->fi;
- free_irq(host->irq, host);
- iounmap(fi->g.mem_base);
- return 0;
- }
- const char *iph5526_info(struct Scsi_Host *host)
- {
- static char buf[80];
- sprintf(buf, "Interphase 5526 Fibre Channel PCI SCSI Adapter using IRQ %dn", host->irq);
- return buf;
- }
- #ifdef MODULE
- #define NAMELEN 8 /* # of chars for storing dev->name */
- static struct net_device *dev_fc[MAX_FC_CARDS];
- static int io;
- static int irq;
- static int bad; /* 0xbad = bad sig or no reset ack */
- static int scsi_registered;
- int init_module(void)
- {
- int i = 0;
- driver_template.module = &__this_module;
- scsi_register_module(MODULE_SCSI_HA, &driver_template);
- if (driver_template.present)
- scsi_registered = TRUE;
- else {
- printk("iph5526: SCSI registeration failed!!!n");
- scsi_registered = FALSE;
- scsi_unregister_module(MODULE_SCSI_HA, &driver_template);
- }
- while(fc[i] != NULL) {
- dev_fc[i] = NULL;
- dev_fc[i] = init_fcdev(dev_fc[i], 0);
- if (dev_fc[i] == NULL) {
- printk("iph5526.c: init_fcdev failed for card #%dn", i+1);
- break;
- }
- dev_fc[i]->irq = irq;
- dev_fc[i]->mem_end = bad;
- dev_fc[i]->base_addr = io;
- dev_fc[i]->init = iph5526_probe;
- dev_fc[i]->priv = fc[i];
- fc[i]->dev = dev_fc[i];
- if (register_fcdev(dev_fc[i]) != 0) {
- kfree(dev_fc[i]);
- dev_fc[i] = NULL;
- if (i == 0) {
- printk("iph5526.c: IP registeration failed!!!n");
- return -ENODEV;
- }
- }
- i++;
- }
- if (i == 0)
- return -ENODEV;
-
- return 0;
- }
- void cleanup_module(void)
- {
- int i = 0;
- while(fc[i] != NULL) {
- struct net_device *dev = fc[i]->dev;
- void *priv = dev->priv;
- fc[i]->g.dont_init = TRUE;
- take_tachyon_offline(fc[i]);
- unregister_fcdev(dev);
- clean_up_memory(fc[i]);
- if (dev->priv)
- kfree(priv);
- kfree(dev);
- dev = NULL;
- i++;
- }
- if (scsi_registered == TRUE)
- scsi_unregister_module(MODULE_SCSI_HA, &driver_template);
- }
- #endif /* MODULE */
- void clean_up_memory(struct fc_info *fi)
- {
- int i,j;
- ENTER("clean_up_memory");
- if (fi->q.ptr_mfsbq_base)
- free_pages((u_long)bus_to_virt(ntohl(*(fi->q.ptr_mfsbq_base))), 5);
- DPRINTK("after kfree2");
- for (i = 0; i < SFSBQ_LENGTH; i++)
- for (j = 0; j < NO_OF_ENTRIES; j++)
- if (fi->q.ptr_sfs_buffers[i*NO_OF_ENTRIES + j])
- kfree(fi->q.ptr_sfs_buffers[i*NO_OF_ENTRIES + j]);
- DPRINTK("after kfree1");
- if (fi->q.ptr_ocq_base)
- free_page((u_long)fi->q.ptr_ocq_base);
- if (fi->q.ptr_imq_base)
- free_page((u_long)fi->q.ptr_imq_base);
- if (fi->q.ptr_mfsbq_base)
- free_page((u_long)fi->q.ptr_mfsbq_base);
- if (fi->q.ptr_sfsbq_base)
- free_page((u_long)fi->q.ptr_sfsbq_base);
- if (fi->q.ptr_edb_base)
- free_pages((u_long)fi->q.ptr_edb_base, 5);
- if (fi->q.ptr_sest_base)
- free_pages((u_long)fi->q.ptr_sest_base, 5);
- if (fi->q.ptr_tachyon_header_base)
- free_page((u_long)fi->q.ptr_tachyon_header_base);
- if (fi->q.ptr_sdb_base)
- free_pages((u_long)fi->q.ptr_sdb_base, 5);
- if (fi->q.ptr_fcp_cmnd_base)
- free_page((u_long)fi->q.ptr_fcp_cmnd_base);
- DPRINTK("after free_pages");
- if (fi->q.ptr_host_ocq_cons_indx)
- kfree(fi->q.ptr_host_ocq_cons_indx);
- if (fi->q.ptr_host_hpcq_cons_indx)
- kfree(fi->q.ptr_host_hpcq_cons_indx);
- if (fi->q.ptr_host_imq_prod_indx)
- kfree(fi->q.ptr_host_imq_prod_indx);
- DPRINTK("after kfree3");
- while (fi->node_info_list) {
- struct fc_node_info *temp_list = fi->node_info_list;
- fi->node_info_list = fi->node_info_list->next;
- kfree(temp_list);
- }
- while (fi->ox_id_list) {
- struct ox_id_els_map *temp = fi->ox_id_list;
- fi->ox_id_list = fi->ox_id_list->next;
- kfree(temp);
- }
- LEAVE("clean_up_memory");
- }
- static int initialize_register_pointers(struct fc_info *fi)
- {
- ENTER("initialize_register_pointers");
- if(fi->g.tachyon_base == 0)
- return -ENOMEM;
-
- fi->i_r.ptr_ichip_hw_control_reg = ICHIP_HW_CONTROL_REG_OFF + fi->g.tachyon_base;
- fi->i_r.ptr_ichip_hw_status_reg = ICHIP_HW_STATUS_REG_OFF + fi->g.tachyon_base;
- fi->i_r.ptr_ichip_hw_addr_mask_reg = ICHIP_HW_ADDR_MASK_REG_OFF + fi->g.tachyon_base;
- fi->t_r.ptr_ocq_base_reg = OCQ_BASE_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_ocq_len_reg = OCQ_LENGTH_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_ocq_prod_indx_reg = OCQ_PRODUCER_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_ocq_cons_indx_reg = OCQ_CONSUMER_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_imq_base_reg = IMQ_BASE_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_imq_len_reg = IMQ_LENGTH_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_imq_cons_indx_reg = IMQ_CONSUMER_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_imq_prod_indx_reg = IMQ_PRODUCER_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_mfsbq_base_reg = MFSBQ_BASE_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_mfsbq_len_reg = MFSBQ_LENGTH_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_mfsbq_prod_reg = MFSBQ_PRODUCER_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_mfsbq_cons_reg = MFSBQ_CONSUMER_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_mfsbuff_len_reg = MFS_LENGTH_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_sfsbq_base_reg = SFSBQ_BASE_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_sfsbq_len_reg = SFSBQ_LENGTH_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_sfsbq_prod_reg = SFSBQ_PRODUCER_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_sfsbq_cons_reg = SFSBQ_CONSUMER_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_sfsbuff_len_reg = SFS_LENGTH_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_sest_base_reg = SEST_BASE_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_sest_len_reg = SEST_LENGTH_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_scsibuff_len_reg = SCSI_LENGTH_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_tach_config_reg = TACHYON_CONFIG_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_tach_control_reg = TACHYON_CONTROL_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_tach_status_reg = TACHYON_STATUS_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_tach_flush_oxid_reg = TACHYON_FLUSH_SEST_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_fm_config_reg = FMGR_CONFIG_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_fm_control_reg = FMGR_CONTROL_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_fm_status_reg = FMGR_STATUS_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_fm_tov_reg = FMGR_TIMER_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_fm_wwn_hi_reg = FMGR_WWN_HI_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_fm_wwn_low_reg = FMGR_WWN_LO_REGISTER_OFFSET + fi->g.tachyon_base;
- fi->t_r.ptr_fm_rx_al_pa_reg = FMGR_RCVD_ALPA_REGISTER_OFFSET + fi->g.tachyon_base;
- LEAVE("initialize_register_pointers");
- return 1;
- }
- /*
- * Local variables:
- * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c iph5526.c"
- * version-control: t
- * kept-new-versions: 5
- * End:
- */