Kernel version specified
[mirror/scst/.git] / mpt / mpt_scst.c
1 /*
2  *  mpt_scst.c
3  *
4  *  Copyright (C) 2005 Beijing Soul Technology Co., Ltd.
5  *  Copyright (C) 2002, 2003, 2004 LSI Logic Corporation
6  *  Copyright (C) 2004 Vladislav Bolkhovitin <vst@vlnb.net>
7  *                and Leonid Stoljar
8  *
9  *  MPT SCSI target mode driver for SCST.
10  * 
11  *  Originally   By: Stephen Shirron
12  *  Port to SCST By: Hu Gang <hugang@soulinfo.com>
13  *
14  *  This program is free software; you can redistribute it and/or
15  *  modify it under the terms of the GNU General Public License
16  *  as published by the Free Software Foundation; either version 2
17  *  of the License, or (at your option) any later version.
18  * 
19  *  This program is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  *  GNU General Public License for more details.
23  *
24  */
25 #include <linux/module.h>
26 #include <linux/init.h>
27 #include <linux/types.h>
28 #include <linux/version.h>
29 #include <linux/blkdev.h>
30 #include <linux/interrupt.h>
31 #include <scsi/scsi.h>
32 #include <scsi/scsi_host.h>
33
34 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
35 #include <linux/pci.h>
36 #endif
37
38 #include "scsi_tgt.h"
39
40 #include <scst_debug.h>
41
42 #include <scst_debug.c>
43 #include <linux/proc_fs.h>
44
45 #include "mpt_scst.h"
46
47 #define MYNAM "mpt_scst"
48
49 #ifdef TRACING
50 static int trace_mpi = 0;
51
52 #define TRACE_MPI       0x80000000
53
54 static char *mpt_state_string[] = {
55         "0",
56         "new",
57         "need data",
58         "data in",
59         "data out",
60         "processed",
61         "NULL",
62 };
63 #endif
64
65 static MPT_STM_PRIV *mpt_stm_priv[MPT_MAX_ADAPTERS+1];
66
67 static int set_aliases_in_fcportpage1 = 1;
68 static int num_aliases = 0;
69 static int stm_context = 0;
70
71 static int mpt_stm_adapter_online(MPT_STM_PRIV *priv);
72 static void mpt_stm_adapter_dispose(MPT_STM_PRIV *priv);
73 static int mpt_stm_adapter_install(MPT_ADAPTER *ioc);
74
75 static int __init _mpt_stm_init(void);
76
77 static void stmapp_set_status(MPT_STM_PRIV *priv, CMD *cmd, int status);
78 static void stmapp_tgt_command(MPT_STM_PRIV *priv, u32 reply_word);
79 static void stm_cmd_buf_post(MPT_STM_PRIV *priv, int index);
80
81 static void stm_tgt_reply_high_pri(MPT_ADAPTER *ioc, 
82                 TargetCmdBufferPostErrorReply_t *rep);
83 static void stm_target_reply_error(MPT_ADAPTER *ioc, TargetErrorReply_t *rep);
84 static void stmapp_target_error(MPT_STM_PRIV *priv, u32 reply_word, int index,
85                 int status, int reason);
86 static void stm_link_service_reply(MPT_ADAPTER *ioc,
87                        LinkServiceBufferPostReply_t *rep);
88 static void stm_link_service_rsp_reply(MPT_ADAPTER *ioc,
89                            LinkServiceRspRequest_t *req, LinkServiceRspReply_t *rep);
90 static void stmapp_set_sense_info(MPT_STM_PRIV *priv,
91                       CMD *cmd, int sense_key, int asc, int ascq);
92 static void stmapp_srr_adjust_offset(MPT_STM_PRIV *priv, int index);
93 static void stmapp_srr_convert_ta_to_tss(MPT_STM_PRIV *priv, int index);
94 static void stmapp_abts_process(MPT_STM_PRIV *priv,
95                     int rx_id, LinkServiceBufferPostReply_t *rep, int index);
96 static int stm_do_config_action(MPT_STM_PRIV *priv,
97                      int action, int type, int number, int address, int length,
98                      int sleep);
99 static int stm_get_config_page(MPT_STM_PRIV *priv,
100                     int type, int number, int address, int sleep);
101 static int stm_set_config_page(MPT_STM_PRIV *priv,
102                     int type, int number, int address, int sleep);
103 static void stm_cmd_buf_post_list(MPT_STM_PRIV *priv, int index);
104 static int stm_send_target_status(MPT_STM_PRIV *priv,
105                        u32 reply_word, int index, int flags, int lun, int tag);
106 static void stm_send_els(MPT_STM_PRIV *priv, LinkServiceBufferPostReply_t *rep,
107              int index, int length);
108 static void stm_link_serv_buf_post(MPT_STM_PRIV *priv, int index);
109
110 static void stm_wait(MPT_STM_PRIV *priv, int milliseconds, int sleep);
111 static int stm_wait_for(MPT_STM_PRIV *priv, volatile int *flag, int seconds,
112              int sleep);
113 static void stmapp_srr_process(MPT_STM_PRIV *priv, int rx_id, int r_ctl, 
114                 u32 offset, LinkServiceBufferPostReply_t *rep, int index);
115
116 static int
117 mpt_proc_read(char *buffer, char **start, off_t offset, int length, int *eof,
118                 struct scst_tgt *scst_tgt)
119 {
120         struct mpt_tgt *tgt = scst_tgt_get_tgt_priv(scst_tgt);
121         MPT_ADAPTER *ioc = tgt->priv->ioc;
122         int res = 0, len = 0;
123         MPT_STM_PRIV *priv = tgt->priv;
124
125         TRACE_ENTRY();
126         TRACE_DBG("res %d, buffer %p, length %d, %d, priv %p, tgt %p", 
127                         res, buffer, length, len, priv, tgt); 
128
129         BUG_ON(tgt == NULL);
130         BUG_ON(ioc == NULL);
131
132         len = snprintf(buffer, length,
133                         "ProductID        :0x%04x (%s)\n"
134                         "Target Enable    :%s\n",
135                         ioc->facts.ProductID,
136                         ioc->prod_name,
137                         tgt->target_enable ? "True" : "False");
138 #define LEN_CHECK(res, buffer, length) \
139         TRACE_DBG("res %d, buffer %p, length %d, %d", res, buffer, length, len); \
140         res += len; buffer += len; length -= len; \
141         if (length <= 0) goto out;
142
143         LEN_CHECK(res, buffer, length)
144
145         if (ioc->bus_type == SCSI) {
146                 int i = 0;
147                 len = snprintf(buffer, length, 
148                                 "Target ID        :%d\n"
149                                 "Capabilities     :0x%x\n"
150                                 "PhysicalInterface:0x%x\n",
151                                 tgt->target_id,
152                                 priv->SCSIPortPage0.Capabilities,
153                                 priv->SCSIPortPage0.PhysicalInterface);
154                 LEN_CHECK(res, buffer, length)
155
156                 len = snprintf(buffer, length,
157                                 "Configuration    :0x%x\n"
158                                 "OnBusTimerValue  :0x%x\n"
159                                 "TargetConfig     :0x%x\n"
160                                 "IDConfig         :0x%x\n",
161                                 priv->SCSIPortPage1.Configuration,
162                                 priv->SCSIPortPage1.OnBusTimerValue,
163                                 priv->SCSIPortPage1.TargetConfig,
164                                 priv->SCSIPortPage1.IDConfig);
165                 LEN_CHECK(res, buffer, length);
166
167                 len = snprintf(buffer, length,
168                                 "PortFlags        :0x%x\n"
169                                 "PortSettings     :0x%x\n",
170                                 priv->SCSIPortPage2.PortFlags,
171                                 priv->SCSIPortPage2.PortSettings);
172                 LEN_CHECK(res, buffer, length);
173 #if 0
174                 for (i = 0; i < 16; i++) {
175                         len = snprintf(buffer, length,
176                                         " DeviceSeting %02d: 0x%x 0x%x 0x%x\n",
177                                         priv->SCSIPortPage2.DeviceSettings[i].Timeout,
178                                         priv->SCSIPortPage2.DeviceSettings[i].SyncFactor,
179                                         priv->SCSIPortPage2.DeviceSettings[i].DeviceFlags);
180                         LEN_CHECK(res, buffer, length);
181                 }
182 #endif
183                 for (i = 0; i < NUM_SCSI_DEVICES; i++) {
184                         len = snprintf(buffer, length, 
185                                         "  Device %02d: 0x%x, 0x%x\n",
186                                         i,
187                                         priv->SCSIDevicePage1[i].RequestedParameters,
188                                         priv->SCSIDevicePage1[i].Configuration);
189                         LEN_CHECK(res, buffer, length);
190                 }
191         }
192
193         if (ioc->bus_type == FC) {
194                 len = snprintf(buffer, length,
195                                 "WWN              :%08X%08X:%08X%08X\n",
196                                 ioc->fc_port_page0[0].WWNN.High,
197                                 ioc->fc_port_page0[0].WWNN.Low,
198                                 ioc->fc_port_page0[0].WWPN.High,
199                                 ioc->fc_port_page0[0].WWPN.Low);
200                 LEN_CHECK(res, buffer, length);
201         }
202 #undef LEN_CHECK
203 out:
204         TRACE_EXIT_RES(res);
205
206         return res;
207 }
208
209 static int
210 mpt_proc_write(struct file *file, const char *buf, unsigned long length, 
211                 struct scst_tgt *scst_tgt)
212 {
213
214         struct mpt_tgt *tgt = scst_tgt_get_tgt_priv(scst_tgt);
215         MPT_ADAPTER *ioc = tgt->priv->ioc;
216         int res = 0;
217         char tmp[32+1];
218
219         TRACE_ENTRY();
220         res = min(32, (int)length);
221         memcpy(tmp, buf, res);
222         tmp[res] = 0;
223
224         TRACE_DBG("buff '%s'", tmp);
225         if (strncmp("target:enable", tmp, strlen("target:enable")) == 0) {
226                 TRACE_DBG("Enable Target, %d, %d", ioc->id, tgt->target_enable);
227                 if (tgt->target_enable != 1) {
228                         mpt_stm_adapter_online(mpt_stm_priv[ioc->id]);
229                         tgt->target_enable = 1;
230                 }
231         }
232
233         if (strncmp("target:disable", tmp, strlen("target:disable")) == 0) {
234                 TRACE_DBG("Disable Target %d, %d", ioc->id, tgt->target_enable);
235                 if (tgt->target_enable != 0) {
236                         /* FIXME */
237                         tgt->target_enable = 0;
238                 }
239         }
240
241 #ifdef DEBUG   
242         if (strncmp("target_id:", tmp, strlen("target_id:")) == 0) {
243                 char *s = tmp + strlen("target_id:");
244                 TRACE_DBG("target id is '%s'", s);
245         }
246 #endif
247
248         TRACE_EXIT_RES(res);
249
250         return length;
251 }
252
253 static int mpt_proc_info(char *buffer, char **start, off_t offset,
254                 int length, int *eof, struct scst_tgt *tgt, int inout)
255 {
256         if (inout) {
257                 return mpt_proc_write(NULL, buffer, length, tgt);
258         }
259         return  mpt_proc_read(buffer, start, offset, length, eof, tgt);
260 }
261
262
263 static int mpt_target_detect(struct scst_tgt_template *temp1);
264 static int mpt_target_release(struct scst_tgt *scst_tgt);
265 static int mpt_xmit_response(struct scst_cmd *scst_cmd);
266 static int mpt_rdy_to_xfer(struct scst_cmd *scst_cmd);
267 static void mpt_on_free_cmd(struct scst_cmd *scst_cmd);
268 static void mpt_task_mgmt_fn_done(struct scst_mgmt_cmd *mcmd);
269 static int mpt_handle_task_mgmt(MPT_STM_PRIV * priv, u32 reply_word,
270                 int task_mgmt, int lun);
271 static int mpt_send_cmd_to_scst(struct mpt_cmd *cmd, int context);
272
273 static struct scst_tgt_template tgt_template = {
274         .name = MYNAM,
275         .sg_tablesize = 128, /* FIXME */
276         .use_clustering = 1,
277 #ifdef DEBUG_WORK_IN_THREAD
278         .xmit_response_atomic = 0,
279         .rdy_to_xfer_atomic = 0,
280 #else
281         .xmit_response_atomic = 1,
282         .rdy_to_xfer_atomic = 1,
283 #endif
284         .detect = mpt_target_detect,
285         .release = mpt_target_release,
286         .xmit_response = mpt_xmit_response,
287         .rdy_to_xfer = mpt_rdy_to_xfer,
288         .on_free_cmd = mpt_on_free_cmd,
289         .task_mgmt_fn_done = mpt_task_mgmt_fn_done,
290         .proc_info = mpt_proc_info,
291 };
292
293 static inline void 
294 mpt_msg_frame_free(MPT_STM_PRIV *priv, int index)
295 {
296         MPT_ADAPTER *ioc = priv->ioc;
297         if (priv->current_mf[index] != NULL) {
298                 TRACE_DBG("%s: free mf index %d, %p", ioc->name,
299                                 MF_TO_INDEX(priv->current_mf[index]), 
300                                 priv->current_mf[index]);
301                 mpt_free_msg_frame(_HANDLE_IOC_ID, priv->current_mf[index]);
302                 priv->current_mf[index] = NULL;
303         }
304 }
305
306 static inline MPT_FRAME_HDR *
307 mpt_msg_frame_alloc(MPT_ADAPTER *ioc, int index)
308 {
309         MPT_STM_PRIV *priv = mpt_stm_priv[ioc->id];
310         MPT_FRAME_HDR *mf;
311
312         if (index != -1) {
313                 TRACE_DBG("%s: current_mf %p, index %d", 
314                                 ioc->name, priv->current_mf[index], index);
315                 WARN_ON(priv->current_mf[index] != NULL);
316         }
317
318         mf = mpt_get_msg_frame(stm_context, _IOC_ID);
319
320         if (mf == NULL) {
321                 BUG_ON(1);
322         }
323         
324         if (index != -1) {
325                 priv->current_mf[index] = mf;
326         }
327
328         TRACE_DBG("%s: alloc mf index %d, %p, %d", ioc->name, 
329                         MF_TO_INDEX(mf), mf, index);
330
331         return mf;
332 }
333
334 static int _mpt_ada_nums = 0;
335
336 static int
337 mptstm_probe(struct pci_dev *pdev, const struct pci_device_id *id)
338 {
339     MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
340     int ret = 0;
341     struct mpt_tgt *tgt;
342     
343     TRACE_ENTRY();
344     ret = mpt_stm_adapter_install(ioc);
345     if (ret != 0) {
346             goto out;
347     }
348
349     tgt = kmalloc(sizeof(*tgt), GFP_KERNEL);
350     TRACE_MEM("kmalloc(GFP_KERNEL) for tgt (%d), %p",
351               sizeof(*tgt), tgt);
352     if (tgt == NULL) {
353             TRACE(TRACE_OUT_OF_MEM, "%s",
354                   "Allocation of tgt failed");
355             ret = -ENOMEM;
356             goto out;
357     }
358     memset(tgt, 0, sizeof(*tgt));
359     tgt->priv = mpt_stm_priv[ioc->id];
360         tgt->target_enable = 0;
361         tgt->target_id = 0;
362     atomic_set(&tgt->sess_count, 0);
363     init_waitqueue_head(&tgt->waitQ);
364     
365     tgt->scst_tgt = scst_register(&tgt_template);
366     if (tgt->scst_tgt == NULL) {
367             PRINT_ERROR(MYNAM ": scst_register() "
368                         "failed for host %p", pdev);
369             
370             ret = -ENODEV;
371             goto out;
372     }
373     scst_tgt_set_tgt_priv(tgt->scst_tgt, tgt);
374     mpt_stm_priv[ioc->id]->tgt = tgt;
375     
376     _mpt_ada_nums ++;
377                         
378  out:
379     
380     TRACE_EXIT_RES(ret);
381     
382     return ret;
383 }
384
385 static void
386 mptstm_remove(struct pci_dev *pdev)
387 {
388     MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
389     MPT_STM_PRIV *priv;
390
391         priv = mpt_stm_priv[ioc->id];
392         if (priv != NULL) {
393                 mpt_stm_adapter_dispose(priv);
394         }
395 }
396
397 static struct mpt_pci_driver mptstm_driver = {
398     .probe = mptstm_probe,
399     .remove = mptstm_remove,
400 };
401
402 /*
403  * mpt_target_detect
404  *
405  * this function is intended to detect the target adapters that are present in
406  * the system. Each found adapter should be registered by calling
407  * scst_register(). The function should return a value >= 0 to signify
408  * the number of detected target adapters. A negative value should be
409  * returned whenever there is an error. 
410  */
411 static int mpt_target_detect(struct scst_tgt_template *templ)
412 {
413         int ret  = 0;
414
415         TRACE_ENTRY();
416         ret = _mpt_stm_init();
417         if (ret != 0) {
418                 goto out;
419         }
420
421         if (mpt_device_driver_register(&mptstm_driver, MPTSTM_DRIVER)) {
422                 printk(KERN_WARNING MYNAM
423                        ": failed to register for device driver callbacks\n");
424                 ret = -ENODEV;
425                 goto out;
426         }
427         
428         ret = _mpt_ada_nums;
429         
430  out:
431         TRACE_EXIT_RES(ret);
432         
433         return ret;
434 }
435
436 static struct scst_cmd *
437 _stm_target_command(MPT_STM_PRIV *priv, int reply_word, 
438                     struct mpt_cmd *mpt_cmd)
439 {
440         u8 *cdb;
441         int lun, tag, dl, alias, index, init_index, task_mgmt;
442         char alias_lun[32];
443         CMD *cmd;
444         struct scst_cmd *scst_cmd;
445         struct mpt_sess *sess = mpt_cmd->sess;
446 #ifdef DEBUG
447         MPT_ADAPTER *ioc = priv->ioc;
448 #endif
449         /* 
450          * Get the CBD, LUN, tag,  Task Mgmt flags, and data length from the 
451          * receive packet 
452          */
453         TRACE_ENTRY();
454
455         index = GET_IO_INDEX(reply_word);
456         init_index = GET_INITIATOR_INDEX(reply_word);
457
458         cmd = &priv->hw->cmd_buf[index];
459
460         if (IsScsi(priv)) {
461                 SCSI_CMD *scsi_cmd = (SCSI_CMD *)cmd->cmd;
462
463                 cdb = scsi_cmd->CDB;
464                 lun = get2bytes(scsi_cmd->LogicalUnitNumber, 0);
465                 tag = scsi_cmd->Tag;
466                 task_mgmt = scsi_cmd->TaskManagementFlags;
467                 dl = 0;
468                 /*TRACE_DBG("AliasID %d, %d", scsi_cmd->AliasID, priv->port_id);*/
469                 if (reply_word & TARGET_MODE_REPLY_ALIAS_MASK) {
470                         alias = (scsi_cmd->AliasID - priv->port_id) & 15;
471                         sprintf(alias_lun, "alias %d lun %d", alias, lun);
472                 } else {
473                         alias = 0;
474                         sprintf(alias_lun, "lun %d", lun);
475                 }
476         } else if (IsSas(priv)) {
477                 SSP_CMD *ssp_cmd = (SSP_CMD *)cmd->cmd;
478
479                 cdb = ssp_cmd->CDB;
480                 lun = get2bytes(ssp_cmd->LogicalUnitNumber, 0);
481                 if (ssp_cmd->FrameType == SSP_TASK_FRAME) {
482                         SSP_TASK        *ssp_task = (SSP_TASK *)cmd->cmd;
483
484                         tag = ssp_task->ManagedTaskTag;
485                         task_mgmt = ssp_task->TaskManagementFunction;
486                 } else {
487                         tag = ssp_cmd->InitiatorTag;
488                         task_mgmt = 0;
489                 }
490                 dl = 0;
491                 alias = 0;
492                 sprintf(alias_lun, "lun %d", lun);
493         } else {
494                 FCP_CMD *fcp_cmd = (FCP_CMD *)cmd->cmd;
495
496                 cdb = fcp_cmd->FcpCdb;
497                 lun = get2bytes(fcp_cmd->FcpLun, 0);
498                 tag = 0;
499                 task_mgmt = fcp_cmd->FcpCntl[2];
500                 dl = be32_to_cpu(fcp_cmd->FcpDl);
501                 if (reply_word & TARGET_MODE_REPLY_ALIAS_MASK) {
502                         alias = fcp_cmd->AliasIndex;
503                         sprintf(alias_lun, "alias %d lun %d", alias, lun);
504                 } else {
505                         alias = 0;
506                         sprintf(alias_lun, "lun %d", lun);
507                 }
508         }
509
510         cmd->reply_word = reply_word;
511         cmd->alias = alias;
512         cmd->lun = lun;
513         cmd->tag = tag;
514
515         TRACE_DBG("%s: cmd %p, re_word %x, alias %x, lun %x, tag %x,"
516                         "%s, init_idx %d, %p, %d",
517                         ioc->name, cmd, reply_word, alias, lun, tag, alias_lun, 
518                         init_index, priv->scst_cmd[index], dl);
519
520         mpt_cmd->CMD = cmd;
521         {
522                 uint16_t _lun = lun;
523                 _lun = swab16(le16_to_cpu(_lun));
524                 scst_cmd = scst_rx_cmd(sess->scst_sess, (uint8_t *)&_lun,
525                                 sizeof(_lun), cdb, MPT_MAX_CDB_LEN, SCST_ATOMIC);
526         }
527         if (scst_cmd == NULL) {
528                 PRINT_ERROR(MYNAM ": scst_rx_cmd() failed for %p", cmd);
529                 goto out;
530         }
531         TRACE_DBG("scst cmd %p, index %d", priv->scst_cmd[index], index);
532
533         WARN_ON(priv->scst_cmd[index] != 0);
534         priv->scst_cmd[index] = scst_cmd;
535
536         scst_cmd_set_tag(scst_cmd, tag);
537         scst_cmd_set_tgt_priv(scst_cmd, mpt_cmd);
538
539         /* FIXME scst_cmd_set_expected */
540 out:
541         TRACE_EXIT();
542
543         return scst_cmd;
544 }
545
546 static void
547 mpt_send_busy(struct mpt_cmd *cmd)
548 {
549         stmapp_set_status(cmd->priv, cmd->CMD, STS_BUSY);
550 }
551
552 static void 
553 mpt_alloc_session_done(struct scst_session *scst_sess, void *data, int result)
554 {
555         struct mpt_sess *sess = (struct mpt_sess *) data;
556         struct mpt_tgt *tgt = sess->tgt;
557         struct mpt_cmd *cmd = NULL;
558         int rc = 0;
559
560         TRACE_ENTRY();
561         if (result == 0) {
562                 scst_sess_set_tgt_priv(scst_sess, sess);
563                 
564                 while (!list_empty(&sess->delayed_cmds)) {
565                         cmd = list_entry(sess->delayed_cmds.next,
566                                          typeof(*cmd), delayed_cmds_entry);
567                         list_del(&cmd->delayed_cmds_entry);
568                         if (rc == 0)
569                                 rc = mpt_send_cmd_to_scst(cmd, SCST_CONTEXT_THREAD);
570                         if (rc != 0) {
571                                 PRINT_INFO(MYNAM ": Unable to get the command, sending BUSY state %p", 
572                                            cmd);
573                                 mpt_send_busy(cmd);
574                                 kfree(cmd);
575                         }
576                 }
577         } else {
578                 PRINT_INFO(MYNAM ": Session initialization failed, "
579                            "sending BUSY status to all deferred commands %p",
580                            cmd);
581                 while (!list_empty(&sess->delayed_cmds)) {
582                         cmd = list_entry(sess->delayed_cmds.next,
583                                          typeof(*cmd), delayed_cmds_entry);
584                         list_del(&cmd->delayed_cmds_entry);
585                         TRACE(TRACE_MGMT, "Command <%p> Busy", cmd);
586                         mpt_send_busy(cmd);
587                         kfree(cmd);
588                 }
589                 tgt->sess[sess->init_index] = NULL;
590                 
591                 TRACE_MEM("kfree for sess %p", sess);
592                 kfree(sess);
593                 
594                 if (atomic_dec_and_test(&tgt->sess_count))
595                                 wake_up_all(&tgt->waitQ);
596         }
597         
598         __clear_bit(MPT_SESS_INITING, &sess->sess_flags);
599
600         TRACE_EXIT();
601         return;
602 }
603
604 static int 
605 mpt_send_cmd_to_scst(struct mpt_cmd *cmd, int context)
606 {
607         int res = 0;
608         
609         TRACE_ENTRY();
610         
611         cmd->scst_cmd = _stm_target_command(cmd->priv, cmd->reply_word, cmd);
612         if (cmd->scst_cmd == NULL) {
613                 res = -EFAULT;
614                 goto out;
615         }
616 #ifdef DEBUG_WORK_IN_THREAD
617         context = SCST_CONTEXT_THREAD;
618 #endif
619         scst_cmd_init_done(cmd->scst_cmd, context);
620
621  out:   
622         TRACE_EXIT_RES(res);
623         
624         return res;
625 }
626
627 static void
628 stm_send_target_status_deferred(MPT_STM_PRIV *priv,
629                 u32 reply_word, int index)
630 {
631         int ret = 0;
632         MPT_ADAPTER         *ioc = priv->ioc;
633         MPT_FRAME_HDR       *mf;
634         TargetStatusSendRequest_t   *req;
635
636         TRACE_ENTRY();
637         mf = priv->status_deferred_mf[index];
638         TRACE_DBG("mf %p, index %d", mf, index);
639         req = (TargetStatusSendRequest_t *)mf;
640
641         priv->io_state[index] |= IO_STATE_STATUS_SENT;
642
643         priv->current_mf[index] = mf;
644         priv->status_deferred_mf[index] = NULL;
645         if (priv->io_state[index] & IO_STATE_HIGH_PRIORITY) {
646                 ret = mpt_send_handshake_request(stm_context, _IOC_ID,
647                                 sizeof(*req), (u32 *)req _HS_SLEEP);
648         } else {
649                 mpt_put_msg_frame(stm_context, _IOC_ID, mf);
650         }
651
652         TRACE_EXIT_RES(ret);
653 }
654
655 static void
656 stm_data_done(MPT_ADAPTER *ioc, u32 reply_word, 
657                 struct scst_cmd *scst_cmd, struct mpt_cmd *cmd, int index)
658 {
659         MPT_STM_PRIV *priv = mpt_stm_priv[ioc->id];
660         uint8_t *buf = NULL;
661
662         TRACE_ENTRY();
663         TRACE_DBG("scst cmd %p, index %d, data done",  scst_cmd, index);
664
665         if (scst_cmd_get_resp_data_len(scst_cmd) > 0) {
666                 TRACE_DBG("clear the data flags <%p>", scst_cmd);
667                 if (scst_cmd_get_sg_cnt(scst_cmd)) {
668                         pci_unmap_sg(priv->ioc->pcidev,
669                                 scst_cmd_get_sg(scst_cmd),
670                                 scst_cmd_get_sg_cnt(scst_cmd),
671                                 scst_to_dma_dir(scst_cmd_get_data_direction(scst_cmd)));
672                 } else {
673                         pci_unmap_single(priv->ioc->pcidev, cmd->dma_handle,
674                                 scst_get_buf_first(scst_cmd, &buf),
675                                 scst_to_dma_dir(scst_cmd_get_data_direction(scst_cmd)));
676                 }
677         }
678         TRACE_EXIT();
679 }
680
681 void 
682 stm_tgt_reply(MPT_ADAPTER *ioc, u32 reply_word)
683 {
684         MPT_STM_PRIV *priv = mpt_stm_priv[ioc->id];
685         int index;
686         struct scst_cmd *scst_cmd;
687         struct mpt_cmd *cmd;
688         volatile int *io_state;
689         
690         TRACE_ENTRY();
691
692         index = GET_IO_INDEX(reply_word);
693         scst_cmd = priv->scst_cmd[index];
694         io_state = priv->io_state + index;
695
696         TRACE_DBG("index %d, state %x, scst cmd %p, current_mf %p",
697                         index, *io_state, scst_cmd, priv->current_mf[index]);
698         /*
699          * if scst_cmd is NULL it show the command buffer not using by 
700          * SCST, let parse the CDB
701          */
702         if (scst_cmd == NULL) {
703                 WARN_ON((*io_state & ~IO_STATE_HIGH_PRIORITY) != IO_STATE_POSTED);
704                 *io_state &= ~IO_STATE_POSTED;
705         
706                 mpt_msg_frame_free(priv, index);
707                 
708                 stmapp_tgt_command(priv, reply_word);
709                 goto out;
710         }
711         
712         cmd = (struct mpt_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
713         TRACE_DBG("scst cmd %p, index %d, cmd %p, cmd state %s", 
714                   scst_cmd, index, cmd, mpt_state_string[cmd->state]);
715         
716         if (cmd->state == MPT_STATE_NEED_DATA) {
717                 int context = SCST_CONTEXT_TASKLET;
718                 int rx_status = SCST_RX_STATUS_SUCCESS;
719
720                 cmd->state = MPT_STATE_DATA_IN;
721
722 #ifdef DEBUG_WORK_IN_THREAD
723                 context = SCST_CONTEXT_THREAD;
724 #endif
725                 TRACE_DBG("Data received, context %x, rx_status %d",
726                                 context, rx_status);
727
728                 BUG_ON(!(*io_state & IO_STATE_DATA_SENT));
729                 mpt_msg_frame_free(priv, index);
730                 if (*io_state & IO_STATE_DATA_SENT) {
731                         *io_state &= ~IO_STATE_DATA_SENT;
732                         stm_data_done(ioc, reply_word, scst_cmd, cmd, index);
733                 }
734 #if 0
735                 if ((*io_state & ~IO_STATE_HIGH_PRIORITY) == IO_STATE_AUTO_REPOST) {
736                         TRACE_DBG("%s", "io state auto repost");
737                         *io_state = IO_STATE_POSTED;
738                 } else if ((*io_state & ~IO_STATE_HIGH_PRIORITY) == 0) {
739                         TRACE_DBG("%s", "io state");
740                         stm_cmd_buf_post(priv, index);
741                 }
742 #endif
743                 scst_rx_data(scst_cmd, rx_status, context);
744
745                 goto out;
746         }
747
748         if (*io_state & IO_STATE_STATUS_SENT) {
749                 /*
750                  *  status (and maybe data too) was being sent, so repost the
751                  *  command buffer
752                  */
753                 *io_state &= ~IO_STATE_STATUS_SENT;
754                 mpt_msg_frame_free(priv, index);
755                 if (*io_state & IO_STATE_DATA_SENT) {
756                         *io_state &= ~IO_STATE_DATA_SENT;
757                         stm_data_done(ioc, reply_word, scst_cmd, cmd, index);
758                 }
759                 if ((*io_state & ~IO_STATE_HIGH_PRIORITY) == IO_STATE_AUTO_REPOST) {
760                         TRACE_DBG("%s", "io state auto repost");
761                         *io_state = IO_STATE_POSTED;
762                 } else if ((*io_state & ~IO_STATE_HIGH_PRIORITY) == 0) {
763                         TRACE_DBG("%s", "io state");
764                         stm_cmd_buf_post(priv, index);
765                 }
766
767                 scst_tgt_cmd_done(scst_cmd);
768
769                 goto out;
770         }
771
772         /*
773          *  data (but not status) was being sent, so if status needs to be
774          *  set now, go ahead and do it; otherwise do nothing
775          */
776         if (*io_state & IO_STATE_DATA_SENT) {
777                 *io_state &= ~IO_STATE_DATA_SENT;
778                 mpt_msg_frame_free(priv, index);
779                 stm_data_done(ioc, reply_word, scst_cmd, cmd, index);
780                 if (*io_state & IO_STATE_STATUS_DEFERRED) {
781                         *io_state &= ~IO_STATE_STATUS_DEFERRED;
782                         stm_send_target_status_deferred(priv, reply_word, index);
783                 }
784                 cmd->state = MPT_STATE_PROCESSED;
785                 goto out;
786         }
787
788         /*
789          * just insert into list
790          * bug how can i handle it 
791          */
792         if (*io_state == 0 && cmd->state == MPT_STATE_NEW) {
793                 WARN_ON(1);
794                 goto out;
795         }
796 #if 0
797         if (*io_state == IO_STATE_POSTED) {
798                 TRACE_DBG("%s", "io state posted");
799                 /*
800                  *  command buffer was posted, so we now have a SCSI command
801                  */
802                 *io_state &= ~IO_STATE_POSTED;
803                 goto out;
804         }
805 #endif
806         WARN_ON(1);
807  out:
808         
809         TRACE_EXIT();
810 }
811
812 static int 
813 mpt_is_task_mgm(MPT_STM_PRIV *priv, u32 reply_word, int *lun)
814 {
815         int task_mgmt = 0, index;
816         CMD *cmd;
817         //struct mpt_tgt *tgt = priv->tgt;
818
819         TRACE_ENTRY();
820
821         index = GET_IO_INDEX(reply_word);
822         cmd = &priv->hw->cmd_buf[index];
823
824         if (IsScsi(priv)) {
825                 SCSI_CMD *scsi_cmd = (SCSI_CMD *)cmd->cmd;
826                 task_mgmt = scsi_cmd->TaskManagementFlags;
827                 *lun = get2bytes(scsi_cmd->LogicalUnitNumber, 0);
828         } else if (IsSas(priv)) {
829                 SSP_CMD *ssp_cmd = (SSP_CMD *)cmd->cmd;
830                 if (ssp_cmd->FrameType == SSP_TASK_FRAME) {
831                         SSP_TASK *ssp_task = (SSP_TASK *)cmd->cmd;
832                         task_mgmt = ssp_task->TaskManagementFunction;
833                 }
834                 *lun = get2bytes(ssp_cmd->LogicalUnitNumber, 0);
835         } else {
836                 FCP_CMD *fcp_cmd = (FCP_CMD *)cmd->cmd;
837                 task_mgmt = fcp_cmd->FcpCntl[2];
838                 *lun = get2bytes(fcp_cmd->FcpLun, 0);
839         }
840         TRACE_EXIT_RES(task_mgmt);
841
842         return task_mgmt;
843 }
844
845 static void
846 stmapp_tgt_command(MPT_STM_PRIV *priv, u32 reply_word)
847 {
848         struct mpt_tgt *tgt = NULL;
849         struct mpt_sess *sess = NULL;
850         struct mpt_cmd *cmd = NULL;
851         int init_index, res = 0, task_mgmt, lun;
852
853         TRACE_ENTRY();
854         
855         tgt = priv->tgt;
856
857         task_mgmt = mpt_is_task_mgm(priv, reply_word, &lun);
858         if (task_mgmt) {
859                 mpt_handle_task_mgmt(priv, reply_word, task_mgmt, lun);
860         }
861         
862         init_index = GET_INITIATOR_INDEX(reply_word);
863         
864         if (test_bit(MPT_TGT_SHUTDOWN, &tgt->tgt_flags)) {
865                 TRACE_DBG("New command while the device %p is shutting down", tgt);
866                 res = -EFAULT;
867                 goto out;
868         }
869         
870         cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
871         TRACE_MEM("kmalloc(GFP_ATOMIC) for cmd (%d): %p", sizeof(*cmd), cmd);
872         if (cmd == NULL) {
873                 TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of cmd failed");
874                 res = -ENOMEM;
875                 goto out;
876         }
877         
878         memset(cmd, 0, sizeof(*cmd));
879         cmd->priv = priv;
880         cmd->reply_word = reply_word;
881         cmd->state = MPT_STATE_NEW;
882
883         sess = tgt->sess[init_index];
884         if (sess == NULL) {
885                 sess = kmalloc(sizeof(*sess), GFP_ATOMIC);
886                 if (sess == NULL) {
887                         TRACE(TRACE_OUT_OF_MEM, "%s",
888                               "Allocation of sess failed");
889                         res = -ENOMEM;
890                         goto out_free_cmd;
891                 }
892                 /* WWPN */
893                 
894                 atomic_inc(&tgt->sess_count);
895                 smp_mb__after_atomic_inc();
896                 
897                 memset(sess, 0, sizeof(*sess));
898                 sess->tgt = tgt;
899                 sess->init_index = init_index;
900                 INIT_LIST_HEAD(&sess->delayed_cmds);
901                 
902                 sess->scst_sess = scst_register_session(tgt->scst_tgt, 1,
903                                                         "", sess, mpt_alloc_session_done);
904                 if (sess->scst_sess == NULL) {
905                         PRINT_ERROR(MYNAM ": scst_register_session failed %p", 
906                                     tgt);
907                         res = -EFAULT;
908                         goto out_free_sess;
909                 }
910                 
911                 __set_bit(MPT_SESS_INITING, &sess->sess_flags);
912                 
913                 tgt->sess[init_index] = sess;
914                 scst_sess_set_tgt_priv(sess->scst_sess, sess);
915                 
916                 cmd->sess = sess;
917                 list_add_tail(&cmd->delayed_cmds_entry, &sess->delayed_cmds);
918                 goto out;
919         }
920
921         /* seesion is ready let us do it */
922         cmd->sess = sess;
923         if (test_bit(MPT_SESS_INITING, &sess->sess_flags)) {
924                 list_add_tail(&cmd->delayed_cmds_entry, &sess->delayed_cmds);
925         } else {
926                 res = mpt_send_cmd_to_scst(cmd, SCST_CONTEXT_TASKLET);
927                 /*res = mpt_send_cmd_to_scst(cmd, SCST_CONTEXT_DIRECT_ATOMIC);*/
928                 if (res != 0)
929                         goto out_free_cmd;
930         }
931         
932  out:
933         TRACE_EXIT();
934         return;
935
936  out_free_sess:
937         TRACE_MEM("kfree for sess %p", sess);
938         kfree(sess);
939
940         if (atomic_dec_and_test(&tgt->sess_count))
941                 wake_up_all(&tgt->waitQ);
942         /* go through */
943  out_free_cmd:
944         TRACE_MEM("kfree for cmd %p", cmd);
945         kfree(cmd);
946         goto out;
947 }
948
949 /*
950  * mpt_target_release
951  * 
952  * this function is
953  * intended to free up the resources allocated to the device. The function
954  * should return 0 to indicate successful release or a negative value if
955  * there are some issues with the release. In the current version of SCST
956  * the return value is ignored. Must be defined.
957  */
958 static int mpt_target_release(struct scst_tgt *scst_tgt)
959 {
960         /* FIXME */
961         return 0;
962 }
963
964 struct mpt_prm
965 {
966         struct mpt_tgt *tgt;
967         uint16_t seg_cnt;
968         unsigned short use_sg;
969         struct scatterlist *sg;
970         unsigned int bufflen;
971         void *buffer;
972         scst_data_direction data_direction;
973         uint16_t rq_result;
974         uint16_t scsi_status;
975         unsigned char *sense_buffer;
976         unsigned int sense_buffer_len;
977         struct mpt_cmd *cmd;
978 };
979
980 static inline void 
981 mpt_dump_sge(MPT_SGE *sge, struct scatterlist *sg)
982 {
983         if (sge) {
984                 void *address = NULL;
985                 struct page *page = NULL;
986                 address = bus_to_virt(sge->address);
987                 page = virt_to_page(address);
988                 TRACE_DBG("address %p, length %x, count %d, page %p", 
989                                 address, sge->length, page_count(page), page);
990                 TRACE_BUFFER("sge data", address, min(sge->length, (u32)0x10));
991         }
992         if (sg) {
993                 TRACE_DBG("sg %p, page %p, %p, offset %d, dma address %x, len %d",
994                                 sg, sg->page, page_address(sg->page), 
995                                 sg->offset, sg->dma_address, sg->length);
996                 TRACE_BUFFER("sg data", page_address(sg->page), (u32)0x10);
997         }
998 }
999
1000 /* FIXME
1001  *
1002  * use_sg can not bigger then NUM_SGES
1003  *
1004  */
1005 static inline void
1006 mpt_sge_to_sgl(struct mpt_prm *prm, MPT_STM_PRIV *priv, MPT_SGL *sgl)
1007 {
1008         unsigned int bufflen = prm->bufflen;
1009         TRACE_ENTRY();
1010         TRACE_DBG("bufflen %d, %p", bufflen, prm->buffer);
1011         if (prm->use_sg) {
1012                 int i;
1013                 prm->sg = (struct scatterlist *)prm->buffer;
1014                 prm->seg_cnt = 
1015                         pci_map_sg(priv->ioc->pcidev, prm->sg, prm->use_sg,
1016                                    scst_to_dma_dir(prm->data_direction));
1017                 
1018                 pci_dma_sync_sg_for_cpu(priv->ioc->pcidev, prm->sg, 
1019                                 prm->use_sg, 
1020                                 scst_to_dma_dir(prm->data_direction));
1021                 for (i = 0; i < prm->use_sg; i++) {
1022                         sgl->sge[i].length = sg_dma_len(&prm->sg[i]);
1023                         sgl->sge[i].address = sg_dma_address(&prm->sg[i]);
1024
1025                         TRACE_DBG("%d, %d", bufflen, prm->sg[i].length);
1026                         if (bufflen < prm->sg[i].length) {
1027                                 sgl->sge[i].length = bufflen;
1028                         }
1029                         mpt_dump_sge(&sgl->sge[i], &prm->sg[i]);
1030                         bufflen -= sgl->sge[i].length;
1031                 }
1032                 pci_dma_sync_sg_for_device(priv->ioc->pcidev, prm->sg, 
1033                                 prm->use_sg, 
1034                                 scst_to_dma_dir(prm->data_direction));
1035         } else {
1036                 prm->cmd->dma_handle = 
1037                         pci_map_single(priv->ioc->pcidev, prm->buffer, 
1038                                        prm->bufflen,
1039                                        scst_to_dma_dir(prm->data_direction));
1040                 
1041                 pci_dma_sync_single_for_cpu(priv->ioc->pcidev, prm->cmd->dma_handle, prm->bufflen, scst_to_dma_dir(prm->data_direction));
1042                 sgl->sge[0].length = prm->bufflen;
1043                 sgl->sge[0].address = virt_to_phys(prm->buffer);
1044                 
1045                 mpt_dump_sge(&sgl->sge[0], NULL);
1046                 pci_dma_sync_single_for_device(priv->ioc->pcidev, prm->cmd->dma_handle, prm->bufflen, scst_to_dma_dir(prm->data_direction));
1047
1048                 prm->seg_cnt = 1;
1049         }
1050         
1051         sgl->num_sges = prm->seg_cnt;
1052         
1053         TRACE_EXIT();
1054 }
1055
1056 static inline void
1057 mpt_set_sense_info(MPT_STM_PRIV *priv, CMD *cmd, int len, u8 *sense_buf)
1058 {
1059         u8 *info = NULL;
1060         
1061         TRACE_ENTRY();
1062
1063         if (IsScsi(priv)) {
1064                 SCSI_RSP    *rsp = (SCSI_RSP *)cmd->rsp;
1065
1066                 rsp->Status = STS_CHECK_CONDITION;
1067                 rsp->Valid |= SCSI_SENSE_LEN_VALID;
1068                 rsp->SenseDataListLength = cpu_to_be32(len);
1069                 info = rsp->SenseData;
1070                 if (rsp->Valid & SCSI_RSP_LEN_VALID) {
1071                         info += be32_to_cpu(rsp->PktFailuresListLength);
1072                 }
1073         } else if (IsSas(priv)) {
1074                 SSP_RSP     *rsp = (SSP_RSP *)cmd->rsp;
1075
1076                 rsp->Status = STS_CHECK_CONDITION;
1077                 rsp->DataPres |= SSP_SENSE_LEN_VALID;
1078                 rsp->SenseDataLength = cpu_to_be32(len);
1079                 info = rsp->ResponseSenseData;
1080                 if (rsp->DataPres & SSP_RSP_LEN_VALID) {
1081                         info += be32_to_cpu(rsp->ResponseDataLength);
1082                 }
1083         } else {
1084                 FCP_RSP     *rsp = (FCP_RSP *)cmd->rsp;
1085
1086                 rsp->FcpStatus = STS_CHECK_CONDITION;
1087                 rsp->FcpFlags |= FCP_SENSE_LEN_VALID;
1088                 rsp->FcpSenseLength = cpu_to_be32(len);
1089                 info = rsp->FcpSenseData - sizeof(rsp->FcpResponseData);
1090                 if (rsp->FcpFlags & FCP_RSP_LEN_VALID) {
1091                         info += be32_to_cpu(rsp->FcpResponseLength);
1092                 }
1093         }
1094
1095         BUG_ON(info == NULL);
1096         memcpy(info, sense_buf, len);
1097 /*out:*/
1098
1099         TRACE_EXIT();
1100 }
1101
1102 static int
1103 mpt_send_tgt_data(MPT_STM_PRIV *priv, u32 reply_word,
1104                 int index, int flags, int lun, int tag, MPT_SGL *sgl,
1105                 int length, int offset)
1106 {
1107         MPT_ADAPTER *ioc = priv->ioc;
1108         TargetAssistRequest_t *req;
1109         MPT_STM_SIMPLE  *sge_simple;
1110         MPT_STM_CHAIN   *sge_chain = NULL;
1111         u32 sge_flags;
1112         int chain_length, i, j, k, init_index, res = 1;
1113         dma_addr_t dma_addr;
1114
1115         TRACE_ENTRY();
1116         req = (TargetAssistRequest_t *)mpt_msg_frame_alloc(ioc,index);
1117         memset(req, 0, sizeof(*req));
1118         
1119         if (priv->exiting) {
1120                 flags &= ~TARGET_ASSIST_FLAGS_REPOST_CMD_BUFFER;
1121         }
1122         
1123         if (priv->io_state[index] & IO_STATE_HIGH_PRIORITY) {
1124                 flags |= TARGET_ASSIST_FLAGS_HIGH_PRIORITY;
1125                 if (flags & TARGET_ASSIST_FLAGS_AUTO_STATUS) {
1126                         flags |= TARGET_ASSIST_FLAGS_REPOST_CMD_BUFFER;
1127                         priv->io_state[index] |= IO_STATE_AUTO_REPOST;
1128                 }
1129         }
1130         
1131         if (priv->fcp2_capable/* && priv->initiators != NULL*/) {
1132                 init_index = GET_INITIATOR_INDEX(reply_word);
1133                 /*init = priv->initiators[init_index];
1134                 if (init != NULL && init->confirm_capable) {
1135                         flags |= TARGET_ASSIST_FLAGS_CONFIRMED;
1136                 }*/
1137         }
1138         TRACE_DBG("flags %x, tag %x, lun %x, offset %x, length %x",
1139                   flags, tag, lun, offset, length);
1140         
1141         req->StatusCode = 0;
1142         req->TargetAssistFlags = (u8)flags;
1143         req->Function = MPI_FUNCTION_TARGET_ASSIST;
1144         req->QueueTag = (u16)tag;
1145         req->ReplyWord = cpu_to_le32(reply_word);
1146         req->LUN[0] = (u8)(lun >> 8);
1147         req->LUN[1] = (u8)lun;
1148         req->RelativeOffset = cpu_to_le32(offset);
1149         req->DataLength = cpu_to_le32(length);
1150         sge_flags =
1151                 MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1152                                   MPI_SGE_FLAGS_MPT_STM_ADDRESSING);
1153         if (flags & TARGET_ASSIST_FLAGS_DATA_DIRECTION)
1154                 sge_flags |= MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_HOST_TO_IOC);
1155         sge_simple = (MPT_STM_SIMPLE *)&req->SGL;
1156         for (i = 0, j = 0, k = 0; i < (int)sgl->num_sges; i++, j++) {
1157                 if (k == 0) {
1158                         /* still in mf, haven't chained yet -- do we need to? */
1159                         if (j == priv->num_sge_target_assist) {
1160                                 /* yes, we need to chain */
1161                                 /* overwrite the last element in the mf with a chain */
1162                                 sge_chain = (MPT_STM_CHAIN *)(sge_simple - 1);
1163                                 sge_chain->Flags =
1164                                         (u8)(MPI_SGE_FLAGS_CHAIN_ELEMENT |
1165                                                  MPI_SGE_FLAGS_MPT_STM_ADDRESSING);
1166                                 dma_addr = priv->hw_dma +
1167                                         ((u8 *)priv->hw->cmd_buf[index].chain_sge - 
1168                                          (u8 *)priv->hw);
1169                                 stm_set_dma_addr(sge_chain->Address, dma_addr);
1170                                 /* set the "last element" flag in the mf */
1171                                 sge_simple = (MPT_STM_SIMPLE *)(sge_chain - 1);
1172                                 sge_simple->FlagsLength |=
1173                                         cpu_to_le32(MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_LAST_ELEMENT));
1174                                 /* redo the last element in the mf */
1175                                 sge_simple =
1176                                         (MPT_STM_SIMPLE *)priv->hw->cmd_buf[index].chain_sge;
1177                                 sge_simple->FlagsLength =
1178                                         cpu_to_le32(sgl->sge[i-1].length | sge_flags);
1179                                 stm_set_dma_addr(sge_simple->Address, sgl->sge[i-1].address);
1180                                 mpt_dump_sge(&sgl->sge[i-1], NULL);
1181                                 sge_simple++;
1182                                 /* say we've chained */
1183                                 req->ChainOffset =
1184                                         ((u8 *)sge_chain - (u8 *)req) / sizeof(u32);
1185                                 j = 1;
1186                                 k++;
1187                         }
1188                 } else {
1189                         /* now in chain, do we need to chain again? */
1190                         if (j == priv->num_sge_chain) {
1191                                 /* yes, we need to chain */
1192                                 /* fix up the previous chain element */
1193                                 chain_length = sizeof(MPT_STM_CHAIN) +
1194                                         (priv->num_sge_chain - 1) * sizeof(MPT_STM_SIMPLE);
1195                                 sge_chain->Length = cpu_to_le16(chain_length);
1196                                 sge_chain->NextChainOffset =
1197                                         (chain_length - sizeof(MPT_STM_CHAIN)) / sizeof(u32);
1198                                 /* overwrite the last element in the chain with another chain */
1199                                 sge_chain = (MPT_STM_CHAIN *)(sge_simple - 1);
1200                                 sge_chain->Flags =
1201                                         (u8)(MPI_SGE_FLAGS_CHAIN_ELEMENT |
1202                                                  MPI_SGE_FLAGS_MPT_STM_ADDRESSING);
1203                                 dma_addr = priv->hw_dma + ((u8 *)sge_simple - (u8 *)priv->hw);
1204                                 stm_set_dma_addr(sge_chain->Address, dma_addr);
1205                                 /* set the "last element" flag in the previous chain */
1206                                 sge_simple = (MPT_STM_SIMPLE *)(sge_chain - 1);
1207                                 sge_simple->FlagsLength |=
1208                                         cpu_to_le32(MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_LAST_ELEMENT));
1209                                 /* redo the last element in the previous chain */
1210                                 sge_simple = (MPT_STM_SIMPLE *)(sge_chain + 1);
1211                                 sge_simple->FlagsLength =
1212                                         cpu_to_le32(sgl->sge[i-1].length | sge_flags);
1213                                 stm_set_dma_addr(sge_simple->Address, sgl->sge[i-1].address);
1214                                 mpt_dump_sge(&sgl->sge[i-1], NULL);
1215                                 sge_simple++;
1216                                 /* say we've chained */
1217                                 j = 1;
1218                                 k++;
1219                         }
1220                 }
1221                 sge_simple->FlagsLength = cpu_to_le32(sgl->sge[i].length | sge_flags);
1222                 stm_set_dma_addr(sge_simple->Address, sgl->sge[i].address);
1223                 mpt_dump_sge(&sgl->sge[i], NULL);
1224                 sge_simple++;
1225         }
1226         /* did we chain? */
1227         if (k != 0) {
1228                 /* fix up the last chain element */
1229                 sge_chain->Length = cpu_to_le16(j * sizeof(MPT_STM_SIMPLE));
1230                 sge_chain->NextChainOffset = 0;
1231         }
1232         /* fix up the last element */
1233         sge_simple--;
1234         sge_simple->FlagsLength |=
1235                 cpu_to_le32(MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_LAST_ELEMENT |
1236                                               MPI_SGE_FLAGS_END_OF_BUFFER |
1237                      MPI_SGE_FLAGS_END_OF_LIST));
1238 #ifdef TRACING
1239 if(trace_mpi)
1240 {
1241         u32 *p = (u32 *)req;
1242         int i;
1243         //dma_addr_t _data;
1244         //u8 *_buf;
1245
1246         TRACE(TRACE_MPI, "%s stm_send_target_data %d",
1247                         ioc->name, index);
1248         for (i = 0; i < (sizeof(*req) - sizeof(req->SGL)) / 4; i++) {
1249                 TRACE(TRACE_MPI, "%s req[%02x] = %08x",
1250                                 ioc->name, i * 4, le32_to_cpu(p[i]));
1251         }
1252         TRACE(TRACE_MPI, "%s num_sges = %d, j = %d, k = %d",
1253                         ioc->name, sgl->num_sges, j, k);
1254         p = (u32 *)&req->SGL;
1255         for (i = 0; i < ((k != 0) ? priv->num_sge_target_assist : j); i++) {
1256 #if MPT_STM_64_BIT_DMA
1257         TRACE(TRACE_MPI, "%s req sgl[%04x] = %08x %08x %08x",
1258                                 ioc->name, i * 12, le32_to_cpu(p[i*3]),
1259                                 le32_to_cpu(p[i*3+1]), le32_to_cpu(p[i*3+2]));
1260 #else
1261         _data = le32_to_cpu(p[i*2+1]);
1262         _buf = (u8 *)phys_to_virt(_data);
1263         TRACE(TRACE_MPI, "%s req sgl[%04x] = %08x %08x,%x,%x,%x,%x,%p",
1264                         ioc->name, i * 8, le32_to_cpu(p[i*2]), le32_to_cpu(p[i*2+1]),
1265                         _buf[0], _buf[1], _buf[2], _buf[3], _buf);
1266 #endif
1267         }
1268         p = (u32 *)priv->hw->cmd_buf[index].chain_sge;
1269         for (i = 0; i < ((k != 0) ? (k - 1) * priv->num_sge_chain + j : 0); i++) {
1270 #if MPT_STM_64_BIT_DMA
1271         TRACE(TRACE_MPI, "%s chain sgl[%04x] = %08x %08x %08x",
1272                         ioc->name, i * 12, le32_to_cpu(p[i*3]),
1273                         le32_to_cpu(p[i*3+1]), le32_to_cpu(p[i*3+2]));
1274 #else
1275         _data = le32_to_cpu(p[i*2+1]);
1276         _buf = (u8 *)phys_to_virt(_data);
1277         TRACE(TRACE_MPI, "%s req sgl[%04x] = %08x %08x,%x,%x,%x,%x,%p",
1278                         ioc->name, i * 8, le32_to_cpu(p[i*2]), le32_to_cpu(p[i*2+1]),
1279                         _buf[0], _buf[1], _buf[2], _buf[3], _buf);
1280 #endif
1281                 }
1282         }
1283 #endif
1284         res = 0;
1285         
1286         priv->io_state[index] |= IO_STATE_DATA_SENT;
1287         if (flags & TARGET_ASSIST_FLAGS_AUTO_STATUS)
1288                 priv->io_state[index] |= IO_STATE_STATUS_SENT;
1289
1290
1291         if (priv->io_state[index] & IO_STATE_HIGH_PRIORITY) {
1292                 res =mpt_send_handshake_request(stm_context, _IOC_ID,
1293                                            ioc->req_sz, (u32 *)req _HS_SLEEP);
1294         } else {
1295                 mpt_put_msg_frame(stm_context, _IOC_ID, (MPT_FRAME_HDR *)req);
1296         }
1297
1298         TRACE_EXIT_RES(res);
1299         
1300         return res;     
1301 }
1302
1303 /* 
1304  * calling mpt_send_target_data
1305  *
1306  */
1307 static void 
1308 mpt_send_target_data(struct mpt_prm *prm, int flags)
1309 {
1310         MPT_STM_PRIV *priv;
1311         u32 reply_word;
1312         int index, lun, tag, length, offset;
1313         MPT_SGL *sgl;
1314         
1315         TRACE_ENTRY();
1316         priv = prm->tgt->priv;
1317         sgl = &priv->sgl;
1318         
1319         mpt_sge_to_sgl(prm, priv, sgl);
1320         
1321         reply_word = prm->cmd->CMD->reply_word;
1322         index = GET_IO_INDEX(reply_word);
1323
1324         lun = prm->cmd->CMD->lun;
1325         tag = prm->cmd->CMD->tag;
1326
1327         if (prm->data_direction == SCST_DATA_READ) {
1328                 flags |= TARGET_ASSIST_FLAGS_DATA_DIRECTION;
1329         }
1330         
1331         length = prm->bufflen;
1332         offset = 0;
1333 #if 0   
1334         TRACE_DBG("priv %p, reply_word %x, index %x, flags %x, lun %x, "
1335                   "tag %x, sgl %p, length %x, offset %x",
1336                   priv, reply_word, index, flags, lun, tag, 
1337                   sgl, length, offset);
1338 #endif  
1339         mpt_send_tgt_data(priv, reply_word, index, flags, lun, tag,
1340                         sgl, length, offset);
1341
1342         TRACE_EXIT();
1343         return;
1344 }
1345
1346 /*
1347  * this function is equivalent to the SCSI queuecommand(). The target should
1348  * transmit the response data and the status in the struct scst_cmd. See
1349  * below for details. Must be defined.
1350  */
1351 static int 
1352 mpt_xmit_response(struct scst_cmd *scst_cmd)
1353 {
1354         int res = SCST_TGT_RES_SUCCESS;
1355         struct mpt_sess *sess;
1356         struct mpt_prm prm = { 0 };
1357         int resp_flags;
1358         //uint16_t full_req_cnt;
1359         //int data_sense_flag = 0;
1360
1361         TRACE_ENTRY();
1362         prm.cmd = (struct mpt_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
1363         sess = (struct mpt_sess *)
1364                 scst_sess_get_tgt_priv(scst_cmd_get_session(scst_cmd));
1365         
1366         prm.sg = NULL;
1367         prm.bufflen = scst_cmd_get_resp_data_len(scst_cmd);
1368         prm.buffer = scst_cmd->sg;
1369         prm.use_sg = scst_cmd->sg_cnt;
1370         prm.data_direction = scst_cmd_get_data_direction(scst_cmd);
1371         prm.rq_result = scst_cmd_get_status(scst_cmd);
1372         prm.sense_buffer = scst_cmd_get_sense_buffer(scst_cmd);
1373         prm.sense_buffer_len = scst_cmd_get_sense_buffer_len(scst_cmd);
1374         prm.tgt = sess->tgt;
1375         prm.seg_cnt = 0;
1376         resp_flags = scst_cmd_get_tgt_resp_flags(scst_cmd);
1377
1378         /* FIXME */
1379         prm.sense_buffer_len = 14;
1380
1381         TRACE_DBG("rq_result=%x, resp_flags=%x, %x, %d", prm.rq_result, 
1382                         resp_flags, prm.bufflen, prm.sense_buffer_len);
1383         if (prm.rq_result != 0)
1384                 TRACE_BUFFER("Sense", prm.sense_buffer, prm.sense_buffer_len);
1385
1386         if ((resp_flags & SCST_TSC_FLAG_STATUS) == 0) {
1387                 /* ToDo, after it's done in SCST */
1388                 PRINT_ERROR(MYNAM ": SCST_TSC_FLAG_STATUS not set: "
1389                             "feature not implemented %p", scst_cmd);
1390                 res = SCST_TGT_RES_FATAL_ERROR;
1391                 goto out_tgt_free;
1392         }
1393         
1394         if (test_bit(MPT_SESS_SHUTDOWN, &sess->sess_flags)) {
1395                 TRACE_DBG("cmd %p while session %p is shutting down",
1396                           prm.cmd, sess);
1397                 res = SCST_TGT_RES_SUCCESS;
1398                 goto out_tgt_free;
1399         }
1400         
1401         if (SCST_SENSE_VALID(prm.sense_buffer)) {
1402                 mpt_set_sense_info(prm.tgt->priv, prm.cmd->CMD, 
1403                                 prm.sense_buffer_len, prm.sense_buffer);
1404         }
1405
1406         if (scst_cmd_get_resp_data_len(scst_cmd) > 0) {
1407                 int flags = 0;
1408                 if (prm.rq_result == 0) {
1409                         flags |= TARGET_ASSIST_FLAGS_AUTO_STATUS;
1410                 }
1411                 if (scst_get_may_need_dma_sync(scst_cmd)) {
1412                         dma_sync_sg(&(prm.tgt->priv->ioc->pcidev->dev),
1413                                 scst_cmd->sg, scst_cmd->sg_cnt,
1414                                 scst_to_tgt_dma_dir(scst_cmd_get_data_direction(scst_cmd)));
1415                 }
1416                 mpt_send_target_data(&prm, flags);
1417                 
1418                 if (prm.rq_result == 0) {
1419                         goto out;
1420                 }
1421         }
1422         {
1423                 int flags = 0;
1424                 u32 reply_word = prm.cmd->CMD->reply_word;
1425                 int index = GET_IO_INDEX(reply_word);
1426                 int lun = prm.cmd->CMD->lun;
1427                 int tag = prm.cmd->CMD->tag;
1428                 MPT_STM_PRIV *priv = prm.tgt->priv;
1429
1430                 if (prm.rq_result == 0) {
1431                         flags |= TARGET_STATUS_SEND_FLAGS_AUTO_GOOD_STATUS;
1432                 }
1433
1434                 flags |= TARGET_STATUS_SEND_FLAGS_REPOST_CMD_BUFFER;
1435                 priv->io_state[index] |= IO_STATE_AUTO_REPOST;
1436
1437                 TRACE_DBG("scst cmd %p, index %d, flags %d",
1438                                 scst_cmd, index, flags);
1439
1440                 stm_send_target_status(priv, reply_word, index, 
1441                                 flags, lun, tag);
1442         }
1443
1444  out:
1445         TRACE_EXIT_RES(res);
1446         
1447         return res;
1448
1449  out_tgt_free:
1450         scst_tgt_cmd_done(scst_cmd);
1451         goto out;
1452 }
1453
1454 /*
1455  * this function 
1456  * informs the driver that data buffer corresponding to the said command
1457  * have now been allocated and it is OK to receive data for this command.
1458  * This function is necessary because a SCSI target does not have any
1459  * control over the commands it receives. Most lower-level protocols have a
1460  * corresponding function which informs the initiator that buffers have
1461  * been allocated e.g., XFER_RDY in Fibre Channel. After the data is
1462  * actually received the low-level driver should call scst_rx_data()
1463  * in order to continue processing this command. Returns one of the
1464  * SCST_TGT_RES_* constants, described below. Pay attention to
1465  * "atomic" attribute of the command, which can be get via
1466  * scst_cmd_get_atomic(): it is true if the function called in the
1467  * atomic (non-sleeping) context. Must be defined.
1468  */
1469 static int mpt_rdy_to_xfer(struct scst_cmd *scst_cmd)
1470 {
1471         int res = SCST_TGT_RES_SUCCESS;
1472         struct mpt_sess *sess;
1473         /*unsigned long flags = 0;*/
1474         struct mpt_prm prm = { 0 };
1475
1476         TRACE_ENTRY();
1477         prm.cmd = (struct mpt_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
1478         sess = (struct mpt_sess *)
1479                 scst_sess_get_tgt_priv(scst_cmd_get_session(scst_cmd));
1480
1481         prm.sg = (struct scatterlist *)NULL;
1482         prm.bufflen = scst_cmd->bufflen;
1483         prm.buffer = scst_cmd->sg;
1484         prm.use_sg = scst_cmd->sg_cnt;
1485         prm.data_direction = scst_cmd_get_data_direction(scst_cmd);
1486         prm.tgt = sess->tgt;
1487         
1488         if (test_bit(MPT_SESS_SHUTDOWN, &sess->sess_flags)) {
1489                 TRACE_DBG("cmd %p while session %p is shutting down",
1490                           prm.cmd, sess);
1491                 scst_rx_data(scst_cmd, SCST_RX_STATUS_ERROR_FATAL,
1492                              SCST_CONTEXT_THREAD);
1493                 res = SCST_TGT_RES_SUCCESS;
1494                 goto out;
1495         }
1496         
1497         prm.cmd->state = MPT_STATE_NEED_DATA;
1498         
1499         mpt_send_target_data(&prm, 0);
1500         
1501  out:
1502         TRACE_EXIT_RES(res);
1503         
1504         return res;
1505 }
1506
1507 /*
1508  * this function
1509  * called to notify the driver that the command is about to be freed.
1510  * Necessary, because for aborted commands <bf/xmit_response()/ could not be
1511  * called. Could be used on IRQ context. Must be defined.
1512  */
1513 static void mpt_on_free_cmd(struct scst_cmd *scst_cmd)
1514 {
1515         struct mpt_cmd *cmd =
1516                 (struct mpt_cmd *)scst_cmd_get_tgt_priv(scst_cmd);
1517         MPT_STM_PRIV *priv = cmd->priv;
1518         int index = GET_IO_INDEX(cmd->reply_word);
1519         //MPT_ADAPTER *ioc = priv->ioc;
1520
1521         TRACE_ENTRY();
1522         
1523         TRACE_DBG("scst_cmd is %p, cmd %p, %p", 
1524                         priv->scst_cmd[index], cmd, scst_cmd);
1525         WARN_ON(priv->scst_cmd[index] != scst_cmd);
1526         priv->scst_cmd[index] = NULL;
1527
1528         scst_cmd_set_tgt_priv(scst_cmd, NULL);
1529
1530 #if 1
1531         memset(cmd, 0, sizeof(*cmd));
1532 #endif
1533         kfree(cmd);
1534
1535         TRACE_EXIT();
1536 }
1537
1538 /*
1539  * this function informs the driver that a received task management
1540  * function has been completed. Completion status could be get via
1541  * scst_mgmt_cmd_get_status(). No return value expected. Must be
1542  * defined, if the target supports task management functionality.
1543  */
1544 static void 
1545 mpt_task_mgmt_fn_done(struct scst_mgmt_cmd *mgmt_cmd)
1546 {
1547         TRACE_ENTRY();
1548         WARN_ON(1);
1549         TRACE_EXIT();
1550 }
1551
1552 static void
1553 mpt_local_task_mgmt(struct mpt_sess *sess, int task_mgmt, int lun)
1554 {
1555         struct mpt_cmd *cmd, *t;
1556         
1557         TRACE_ENTRY();
1558         switch (task_mgmt) {
1559         case IMM_NTFY_TARGET_RESET:
1560                 while (!list_empty(&sess->delayed_cmds)) {
1561                         cmd = list_entry(sess->delayed_cmds.next,
1562                                          typeof(*cmd), delayed_cmds_entry);
1563                         list_del(&cmd->delayed_cmds_entry);
1564                         kfree(cmd);
1565                 }
1566                 break;
1567
1568         case IMM_NTFY_LUN_RESET1:
1569         case IMM_NTFY_LUN_RESET2:
1570         case IMM_NTFY_CLEAR_TS:
1571         case IMM_NTFY_ABORT_TS:
1572                 list_for_each_entry_safe(cmd, t, &sess->delayed_cmds,
1573                                          delayed_cmds_entry)
1574                         {
1575                                 if (cmd->CMD->lun == lun) {
1576                                         list_del(&cmd->delayed_cmds_entry);
1577                                         kfree(cmd);
1578                                 }
1579                         }
1580                 break;
1581                 
1582         case IMM_NTFY_CLEAR_ACA:
1583         default:
1584                 break;
1585         }
1586         TRACE_EXIT();
1587 }
1588
1589 static int 
1590 mpt_handle_task_mgmt(MPT_STM_PRIV *priv, u32 reply_word,
1591                      int task_mgmt, int _lun)
1592 {
1593         int res = 0, rc = 0;
1594         struct mpt_mgmt_cmd *mcmd;
1595         struct mpt_tgt *tgt;
1596         struct mpt_sess *sess;
1597         int init_index;
1598         uint16_t lun = _lun;
1599
1600         TRACE_ENTRY();
1601         
1602         TRACE_DBG("task_mgmt %d", task_mgmt);
1603         tgt = priv->tgt;
1604         init_index = GET_INITIATOR_INDEX(reply_word);
1605         
1606         sess = tgt->sess[init_index];
1607         if (sess == NULL) {
1608                 TRACE(TRACE_MGMT, "mpt_scst(%s): task mgmt fn %p for "
1609                       "unexisting session", priv->ioc->name, tgt);
1610                 res = -EFAULT;
1611                 goto out;
1612         }
1613         
1614         if (test_bit(MPT_SESS_INITING, &sess->sess_flags)) {
1615                 TRACE(TRACE_MGMT, "mpt_scst(%s): task mgmt fn %p for "
1616                       "inited session", priv->ioc->name, tgt);
1617                 mpt_local_task_mgmt(sess, reply_word, task_mgmt);
1618                 res = -EFAULT;
1619                 goto out;
1620         }
1621         
1622         mcmd = kmalloc(sizeof(*mcmd), GFP_ATOMIC);
1623         TRACE_MEM("kmalloc(GFP_ATOMIC) for mcmd (%d): %p",
1624                   sizeof(*mcmd), mcmd);
1625         if (mcmd == NULL) {
1626                 TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of mgmt cmd failed");
1627                 res = -ENOMEM;
1628                 goto out;
1629         }
1630
1631         memset(mcmd, 0, sizeof(*mcmd));
1632         mcmd->sess = sess;
1633         mcmd->task_mgmt = task_mgmt;
1634         
1635         switch(task_mgmt) {
1636         case IMM_NTFY_CLEAR_ACA:
1637                 TRACE(TRACE_MGMT, "%s", "IMM_NTFY_CLEAR_ACA received");
1638                 rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_CLEAR_ACA,
1639                                          (uint8_t *)&lun, sizeof(lun),
1640                                          SCST_ATOMIC, mcmd);
1641                 break;
1642         case IMM_NTFY_TARGET_RESET:
1643                 TRACE(TRACE_MGMT, "%s", "IMM_NTFY_TARGET_RESET received");
1644                 rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_TARGET_RESET,
1645                                          (uint8_t *)&lun, sizeof(lun),
1646                                          SCST_ATOMIC, mcmd);
1647                 break;
1648         case IMM_NTFY_LUN_RESET1:
1649         case IMM_NTFY_LUN_RESET2:
1650                 TRACE(TRACE_MGMT, "%s", "IMM_NTFY_LUN_RESET received");
1651                 rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_LUN_RESET,
1652                                          (uint8_t *)&lun, sizeof(lun),
1653                                          SCST_ATOMIC, mcmd);
1654                 break;
1655         case IMM_NTFY_CLEAR_TS:
1656                 TRACE(TRACE_MGMT, "%s", "IMM_NTFY_CLEAR_TS received");
1657                 rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_CLEAR_TASK_SET,
1658                                          (uint8_t *)&lun, sizeof(lun),
1659                                          SCST_ATOMIC, mcmd);
1660                 break;
1661                 
1662         case IMM_NTFY_ABORT_TS:
1663                 TRACE(TRACE_MGMT, "%s", "IMM_NTFY_ABORT_TS received");
1664                 rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_ABORT_TASK_SET,
1665                                          (uint8_t *)&lun, sizeof(lun),
1666                                          SCST_ATOMIC, mcmd);
1667                 break;
1668
1669         default:
1670                 PRINT_ERROR("mpt_scst(%s): Unknown task mgmt fn 0x%x",
1671                             priv->ioc->name, task_mgmt);
1672                 break;
1673         }
1674         if (rc != 0) {
1675                 PRINT_ERROR("mpt_scst(%s): scst_rx_mgmt_fn_lun() failed: %d",
1676                             priv->ioc->name, rc);
1677                 res = -EFAULT;
1678                 goto out_free;
1679         }
1680
1681  out:
1682         TRACE_EXIT_RES(res);
1683         return res;
1684
1685  out_free:
1686         TRACE_MEM("kmem_cache_free for mcmd %p", mcmd);
1687         kfree(mcmd);
1688         goto out;
1689 }
1690
1691
1692
1693 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1694 /*
1695  *  called when any target mode reply is received
1696  *  if mf_req is null, then this is a turbo reply; otherwise it's not
1697  */
1698 static int
1699 stm_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf_req, MPT_FRAME_HDR *mf_rep)
1700 {
1701     MPT_STM_PRIV        *priv = mpt_stm_priv[ioc->id];
1702     MPIDefaultReply_t   *rep = (MPIDefaultReply_t *)mf_rep;
1703     int ioc_status;
1704
1705         TRACE_ENTRY();
1706         if (mf_req == NULL) {
1707                 TRACE_DBG("%s: got turbo reply, reply %x",
1708                                 ioc->name, CAST_PTR_TO_U32(mf_rep));
1709                 /*
1710                  *  this is a received SCSI command, so go handle it
1711                  */
1712                 stm_tgt_reply(ioc, CAST_PTR_TO_U32(mf_rep));
1713                 return 0;
1714         }
1715
1716 #if 0
1717     if (rep->Function == MPI_FUNCTION_EVENT_NOTIFICATION) {
1718         /*
1719          *  this is an event notification -- do nothing for now
1720          *  (this short-cuts the switch() below and avoids the printk)
1721          */
1722         return (0);
1723     }
1724 #endif
1725     ioc_status = le16_to_cpu(rep->IOCStatus);
1726
1727     TRACE_DBG("%s: request %p, reply %p (%02x), %d",
1728               ioc->name, mf_req, mf_rep, rep->Function, ioc_status);
1729     TRACE_DBG("%s: mf index = %d", ioc->name, MF_TO_INDEX(mf_req));
1730
1731         if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
1732                 TRACE_DBG("%s Function = %02x, IOCStatus = %04x, IOCLogInfo = %08x",
1733                                 ioc->name, rep->Function, ioc_status,
1734                                 le32_to_cpu(rep->IOCLogInfo));
1735         }
1736
1737     ioc_status &= MPI_IOCSTATUS_MASK;
1738     switch (rep->Function) {
1739         case MPI_FUNCTION_CONFIG:
1740             /*
1741              *  this signals that the config is done
1742              */
1743             priv->config_pending = 0;
1744             memcpy(&priv->config_rep, rep, sizeof(ConfigReply_t));
1745             /*
1746              *  don't free the message frame, since we're remembering it
1747              *  in priv->config_mf, and we'll be using it over and over
1748              */
1749             return (0);
1750
1751         case MPI_FUNCTION_PORT_ENABLE:
1752             /*
1753              *  this signals that the port enable is done
1754              */
1755             priv->port_enable_loginfo = le32_to_cpu(rep->IOCLogInfo);
1756             priv->port_enable_pending = 0;
1757             return (1);
1758
1759         case MPI_FUNCTION_TARGET_CMD_BUFFER_POST:
1760         case MPI_FUNCTION_TARGET_CMD_BUF_LIST_POST:
1761             /*
1762              *  this is the response to a command buffer post; if status
1763              *  is success, then this just acknowledges the posting of a
1764              *  command buffer, so do nothing
1765              *
1766              *  we can also get here for High Priority I/O (such as getting
1767              *  a command while not being allowed to disconnect from the SCSI
1768              *  bus), and if we're shutting down
1769              */
1770                 if (ioc_status == MPI_IOCSTATUS_SUCCESS) {
1771                         TRACE_EXIT();
1772                         return 1;
1773                 }
1774                 if (priv->target_mode_abort_pending &&
1775                                 ioc_status == MPI_IOCSTATUS_TARGET_ABORTED) {
1776                         TRACE_EXIT();
1777                         return (0);
1778                 }
1779                 if (ioc_status == MPI_IOCSTATUS_TARGET_PRIORITY_IO) {
1780                         stm_tgt_reply_high_pri(ioc,
1781                                         (TargetCmdBufferPostErrorReply_t *)rep);
1782                         TRACE_EXIT();
1783                         return (0);
1784                 }
1785                 TRACE_DBG(":%s TargetCmdBufPostReq IOCStatus = %04x",
1786                                 ioc->name, ioc_status);
1787                 if (ioc_status == MPI_IOCSTATUS_INSUFFICIENT_RESOURCES) {
1788                         /*
1789                          *  this should never happen since we carefully count
1790                          *  our resources, but if it does, tolerate it -- don't
1791                          *  repost the errant command buffer, lest we create an
1792                          *  endless loop
1793                          */
1794                         WARN_ON(1);
1795                         return (0);
1796                 }
1797                 if (ioc_status == MPI_IOCSTATUS_TARGET_NO_CONNECTION) {
1798                         printk(KERN_ERR MYNAM 
1799                                         ": %s: Got MPI_IOCSTATUS_TARGET_NO_CONNECTION\n",
1800                                         ioc->name);
1801                         return (0);
1802                 }
1803                 if (rep->MsgLength > sizeof(*rep)/sizeof(u32)) {
1804                         TRACE_DBG("MsgLength is %d, %d", 
1805                                         rep->MsgLength, sizeof(*rep)/sizeof(u32));
1806                         WARN_ON(1);
1807                         /*
1808                          *  the TargetCmdBufferPostErrorReply and TargetErrorReply
1809                          *  structures are nearly identical; the exception is that
1810                          *  the former does not have a TransferCount field, while
1811                          *  the latter does; add one
1812                          */
1813                         ((TargetErrorReply_t *)rep)->TransferCount = 0;
1814                         stm_target_reply_error(ioc, (TargetErrorReply_t *)rep);
1815                         return (0);
1816                 }
1817                 WARN_ON(1);
1818             return (1);
1819
1820         case MPI_FUNCTION_TARGET_CMD_BUF_BASE_POST:
1821             /*
1822              *  this signals that the command buffer base post is done
1823              */
1824             if (ioc_status != MPI_IOCSTATUS_SUCCESS) {
1825                 printk(KERN_ERR MYNAM ":%s TargetCmdBufPostBaseReq IOCStatus = %04x\n",
1826                        ioc->name, ioc_status);
1827             }
1828             return (1);
1829
1830         case MPI_FUNCTION_TARGET_ASSIST:
1831             /*
1832              *  this is the response to a target assist command; we should
1833              *  only get here if an error occurred
1834              *
1835              *  at this point we need to clean up the remains of the I/O
1836              *  and repost the command buffer
1837              */
1838             if (ioc_status != MPI_IOCSTATUS_SUCCESS) {
1839                 printk(KERN_ERR MYNAM ":%s TargetAssistReq IOCStatus = %04x\n",
1840                        ioc->name, ioc_status);
1841             }
1842             stm_target_reply_error(ioc, (TargetErrorReply_t *)rep);
1843             return (0);
1844
1845         case MPI_FUNCTION_TARGET_STATUS_SEND:
1846             /*
1847              *  this is the response to a target status send command; we should
1848              *  only get here if an error occurred
1849              *
1850              *  at this point we need to clean up the remains of the I/O
1851              *  and repost the command buffer
1852              */
1853             if (ioc_status != MPI_IOCSTATUS_SUCCESS) {
1854                 printk(KERN_ERR MYNAM ":%s TargetStatusSendReq IOCStatus = %04x\n",
1855                        ioc->name, ioc_status);
1856             }
1857             stm_target_reply_error(ioc, (TargetErrorReply_t *)rep);
1858             return (0);
1859
1860         case MPI_FUNCTION_TARGET_MODE_ABORT: {
1861             TargetModeAbort_t           *req = (TargetModeAbort_t *)mf_req;
1862
1863             /*
1864              *  this signals that the target mode abort is done
1865              */
1866             if (ioc_status != MPI_IOCSTATUS_SUCCESS) {
1867                 printk(KERN_ERR MYNAM ":%s TargetModeAbort IOCStatus = %04x\n",
1868                        ioc->name, ioc_status);
1869             }
1870             if (req->AbortType == TARGET_MODE_ABORT_TYPE_ALL_CMD_BUFFERS) {
1871                 priv->target_mode_abort_pending = 0;
1872             } else {
1873                 u32             reply_word;
1874                 int             index;
1875                 volatile int    *io_state;
1876
1877                 /*
1878                  *  a target mode abort has finished, so check to see if
1879                  *  the I/O was aborted, but there was no error reply for
1880                  *  that aborted I/O (this will be the case for I/Os that
1881                  *  have no outstanding target assist or target status send
1882                  *  at the time of the abort request) -- so pretend that
1883                  *  the error reply came in with a status indicating that
1884                  *  the I/O was aborted
1885                  */
1886                 reply_word = le32_to_cpu(req->ReplyWord);
1887                 index = GET_IO_INDEX(reply_word);
1888                 io_state = priv->io_state + index;
1889                 if ((*io_state & IO_STATE_ABORTED) &&
1890                     !(*io_state & IO_STATE_DATA_SENT) &&
1891                     !(*io_state & IO_STATE_STATUS_SENT)) {
1892                     stmapp_target_error(priv, reply_word, index,
1893                                         MPI_IOCSTATUS_TARGET_ABORTED, 0);
1894                 }
1895                 /*
1896                 *  see if we were trying to abort a target assist or target
1897                 *  status send, but the abort didn't work (if the abort had
1898                 *  worked, the flag we're checking would be clear) -- if so,
1899                 *  just clear the various SRR flags, and wait for the initiator
1900                 *  to retry the SRR
1901                 */
1902                 if (*io_state & IO_STATE_REQUEST_ABORTED) {
1903                     printk(KERN_ERR MYNAM ":%s index %d: io_state = %x\n",
1904                            ioc->name, index, *io_state);
1905                     printk(KERN_ERR MYNAM ":%s   request was not aborted\n",
1906                            ioc->name);
1907                     *io_state &= ~IO_STATE_REQUEST_ABORTED;
1908                     *io_state &= ~IO_STATE_REISSUE_REQUEST;
1909                     *io_state &= ~IO_STATE_ADJUST_OFFSET;
1910                     *io_state &= ~IO_STATE_CONVERT_TA_TO_TSS;
1911                     *io_state &= ~IO_STATE_REDO_COMMAND;
1912                 }
1913             }
1914                 TRACE_EXIT_RES(1);
1915             return (1);
1916         }
1917
1918         case MPI_FUNCTION_FC_LINK_SRVC_BUF_POST:
1919             /*
1920              *  if the length is that of a default reply, then this is the
1921              *  response to a link service buffer post -- do nothing except
1922              *  report errors (none are expected); otherwise this is a
1923              *  received ELS, so go handle it
1924              */
1925             if (ioc_status != MPI_IOCSTATUS_SUCCESS) {
1926                 if (priv->link_serv_abort_pending &&
1927                     ioc_status == MPI_IOCSTATUS_FC_ABORTED) {
1928                     return (0);
1929                 }
1930                 printk(KERN_ERR MYNAM ":%s FcLinkServBufPostReq IOCStatus = %04x\n",
1931                        ioc->name, ioc_status);
1932             }
1933             if (rep->MsgLength > sizeof(*rep)/sizeof(u32)) {
1934                 stm_link_service_reply(ioc,
1935                                        (LinkServiceBufferPostReply_t *)rep);
1936                 return (0);
1937             }
1938             return (1);
1939
1940         case MPI_FUNCTION_FC_LINK_SRVC_RSP:
1941             /*
1942              *  this is the response to a link service send -- repost the
1943              *  link service command buffer
1944              */
1945             if (ioc_status != MPI_IOCSTATUS_SUCCESS) {
1946                 printk(KERN_ERR MYNAM ":%s FcLinkServRspReq IOCStatus = %04x\n",
1947                        ioc->name, ioc_status);
1948             }
1949             stm_link_service_rsp_reply(ioc,
1950                                        (LinkServiceRspRequest_t *)mf_req,
1951                                        (LinkServiceRspReply_t *)mf_rep);
1952             return (1);
1953
1954         case MPI_FUNCTION_FC_ABORT:
1955             /*
1956              *  this signals that the target mode abort is done
1957              */
1958             if (ioc_status != MPI_IOCSTATUS_SUCCESS) {
1959                 printk(KERN_ERR MYNAM ":%s FcAbort IOCStatus = %04x\n",
1960                        ioc->name, ioc_status);
1961             }
1962             priv->link_serv_abort_pending = 0;
1963             return (1);
1964
1965         case MPI_FUNCTION_FC_PRIMITIVE_SEND:
1966             /*
1967              *  this signals that the FC primitive send is done
1968              */
1969             if (ioc_status != MPI_IOCSTATUS_SUCCESS) {
1970                 printk(KERN_ERR MYNAM ":%s FcPrimitiveSend IOCStatus = %04x\n",
1971                        ioc->name, ioc_status);
1972             }
1973             priv->fc_primitive_send_pending = 0;
1974             return (1);
1975
1976         case MPI_FUNCTION_FC_EX_LINK_SRVC_SEND:
1977             /*
1978              *  this signals that the extended link service send is done
1979              */
1980             if (ioc_status != MPI_IOCSTATUS_SUCCESS) {
1981                 printk(KERN_ERR MYNAM ":%s ExLinkServiceSend IOCStatus = %04x\n",
1982                        ioc->name, ioc_status);
1983             }
1984             priv->ex_link_service_send_pending = 0;
1985             return (1);
1986
1987         default:
1988             /*
1989              *  don't understand this reply, so dump to the screen
1990              */
1991             printk(KERN_ERR MYNAM ":%s got a reply (function %02x) that "
1992                    "I don't know what to do with\n", ioc->name, rep->Function);
1993 if(1)
1994 {
1995             u32 *p = (u32 *)mf_req;
1996             int i;
1997
1998             for (i = 0; i < 16; i++) {
1999                 printk("%s mf_req[%02x] = %08x\n",
2000                        ioc->name, i * 4, le32_to_cpu(p[i]));
2001             }
2002 }
2003 if(1)
2004 {
2005             u32 *p = (u32 *)mf_rep;
2006             int i;
2007
2008             for (i = 0; i < 16; i++) {
2009                 printk("%s mf_rep[%02x] = %08x\n",
2010                        ioc->name, i * 4, le32_to_cpu(p[i]));
2011             }
2012 }
2013             break;
2014     }
2015         TRACE_EXIT();
2016     return (0);
2017 }
2018
2019 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2020 static void
2021 stm_tgt_reply_high_pri(MPT_ADAPTER *ioc, TargetCmdBufferPostErrorReply_t *rep)
2022 {
2023         MPT_STM_PRIV    *priv = mpt_stm_priv[ioc->id];
2024         u32                     reply_word;
2025         int                     reason;
2026         int                     index;
2027
2028         TRACE_ENTRY();
2029         reply_word = le32_to_cpu(rep->ReplyWord);
2030         reason = rep->PriorityReason;
2031
2032         index = GET_IO_INDEX(reply_word);
2033
2034         TRACE_DBG("%s: target reply high priority", ioc->name);
2035         TRACE_DBG("%s: ReplyWord = %08x, PriorityReason = %02x",
2036                         ioc->name, reply_word, reason);
2037
2038         priv->io_state[index] |= IO_STATE_HIGH_PRIORITY;
2039         if (reason == PRIORITY_REASON_NO_DISCONNECT ||
2040                         reason == PRIORITY_REASON_SCSI_TASK_MANAGEMENT) {
2041                 stm_tgt_reply(ioc, reply_word);
2042                 goto out;       
2043         } 
2044
2045         WARN_ON(1);
2046         if (reason == PRIORITY_REASON_TARGET_BUSY) {
2047                 CMD             *cmd;
2048                 int             lun;
2049                 int             tag;
2050
2051                 priv->io_state[index] &= ~IO_STATE_POSTED;
2052                 cmd = &priv->hw->cmd_buf[index];
2053                 if (IsScsi(priv)) {
2054                         SCSI_CMD        *scsi_cmd = (SCSI_CMD *)cmd->cmd;
2055
2056                         lun = get2bytes(scsi_cmd->LogicalUnitNumber, 0);
2057                         tag = scsi_cmd->Tag;
2058                 } else if (IsSas(priv)) {
2059                         SSP_CMD *ssp_cmd = (SSP_CMD *)cmd->cmd;
2060
2061                         lun = get2bytes(ssp_cmd->LogicalUnitNumber, 0);
2062                         tag = ssp_cmd->InitiatorTag;
2063                 } else {
2064                         FCP_CMD *fcp_cmd = (FCP_CMD *)cmd->cmd;
2065
2066                         lun = get2bytes(fcp_cmd->FcpLun, 0);
2067                         tag = 0;
2068                 }
2069                 memset(cmd->rsp, 0, sizeof(cmd->rsp));
2070                 stmapp_set_status(priv, cmd, STS_TASK_SET_FULL);
2071                 stm_send_target_status(priv, reply_word, index, 0, lun, tag);
2072         } else {
2073                 stmapp_target_error(priv, reply_word, index,
2074                                 MPI_IOCSTATUS_TARGET_PRIORITY_IO, reason);
2075         }
2076 out:
2077         TRACE_EXIT();
2078 }
2079
2080 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2081 static void
2082 stm_target_reply_error(MPT_ADAPTER *ioc,
2083                        TargetErrorReply_t *rep)
2084 {
2085     MPT_STM_PRIV        *priv = mpt_stm_priv[ioc->id];
2086     u32                 reply_word;
2087     int                 index;
2088     int                 status;
2089     int                 reason;
2090     volatile int        *io_state;
2091
2092         TRACE_ENTRY();
2093     reply_word = le32_to_cpu(rep->ReplyWord);
2094     status = le16_to_cpu(rep->IOCStatus) & MPI_IOCSTATUS_MASK;
2095
2096     index = GET_IO_INDEX(reply_word);
2097
2098     io_state = priv->io_state + index;
2099
2100         if (status == MPI_IOCSTATUS_TARGET_PRIORITY_IO) {
2101                 reason = rep->PriorityReason;
2102                 *io_state |= IO_STATE_HIGH_PRIORITY;
2103         } else {
2104                 reason = 0;
2105         }
2106
2107     TRACE_DBG("%s: target reply error", ioc->name);
2108     TRACE_DBG("%s: ReplyWord = %08x, IOCStatus = %04x",
2109            ioc->name, reply_word, status);
2110
2111         if (*io_state & IO_STATE_REQUEST_ABORTED) {
2112                 TRACE_DBG("%s: index %d: io_state = %x",
2113                                 ioc->name, index, *io_state);
2114                 TRACE_DBG("%s:   request was aborted", ioc->name);
2115                 *io_state &= ~IO_STATE_REQUEST_ABORTED;
2116                 if (*io_state & IO_STATE_REISSUE_REQUEST) {
2117                         *io_state &= ~IO_STATE_REISSUE_REQUEST;
2118                         TRACE_DBG("%s:   being reissued", ioc->name);
2119                         if (*io_state & IO_STATE_ADJUST_OFFSET) {
2120                                 *io_state &= ~IO_STATE_ADJUST_OFFSET;
2121                                 stmapp_srr_adjust_offset(priv, index);
2122                         }
2123                         if (*io_state & IO_STATE_CONVERT_TA_TO_TSS) {
2124                                 *io_state &= ~IO_STATE_CONVERT_TA_TO_TSS;
2125                                 stmapp_srr_convert_ta_to_tss(priv, index);
2126                                 goto out;
2127                         }
2128                         if (*io_state & IO_STATE_REDO_COMMAND) {
2129                                 *io_state &= ~IO_STATE_REDO_COMMAND;
2130                                 *io_state &= ~IO_STATE_DATA_SENT;
2131                                 *io_state &= ~IO_STATE_STATUS_SENT;
2132                                 mpt_free_msg_frame(_HANDLE_IOC_ID, priv->current_mf[index]);
2133                                 stmapp_tgt_command(priv, reply_word);
2134                                 goto out;
2135                         }
2136                         mpt_put_msg_frame(stm_context, _IOC_ID, priv->current_mf[index]);
2137                         goto out;
2138                 }
2139         }
2140
2141     stmapp_target_error(priv, reply_word, index, status, reason);
2142 out:
2143         TRACE_EXIT();
2144 }
2145
2146 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2147 static void
2148 stm_target_cleanup(MPT_STM_PRIV *priv,
2149                    int index)
2150 {
2151     MPT_ADAPTER         *ioc = priv->ioc;
2152     volatile int        *io_state;
2153
2154         TRACE_ENTRY();
2155         io_state = priv->io_state + index;
2156         if (*io_state & (IO_STATE_DATA_SENT | IO_STATE_STATUS_SENT)) {
2157                 *io_state &= ~IO_STATE_DATA_SENT;
2158                 *io_state &= ~IO_STATE_STATUS_SENT;
2159                 mpt_free_msg_frame(_HANDLE_IOC_ID, priv->current_mf[index]);
2160         }
2161         if (*io_state & IO_STATE_STATUS_DEFERRED) {
2162                 *io_state &= ~IO_STATE_STATUS_DEFERRED;
2163                 mpt_free_msg_frame(_HANDLE_IOC_ID, priv->status_deferred_mf[index]);
2164         }
2165         *io_state &= ~IO_STATE_REISSUE_REQUEST;
2166         *io_state &= ~IO_STATE_ADJUST_OFFSET;
2167         *io_state &= ~IO_STATE_CONVERT_TA_TO_TSS;
2168         *io_state &= ~IO_STATE_REDO_COMMAND;
2169         *io_state &= ~IO_STATE_REQUEST_ABORTED;
2170         *io_state &= ~IO_STATE_INCOMPLETE;
2171         //  *io_state &= ~IO_STATE_AUTO_REPOST;
2172         *io_state &= ~IO_STATE_ABORTED;
2173         *io_state &= ~IO_STATE_POSTED;
2174         if ((*io_state & ~IO_STATE_HIGH_PRIORITY) == IO_STATE_AUTO_REPOST) {
2175                 *io_state = IO_STATE_POSTED;
2176         } else if ((*io_state & ~IO_STATE_HIGH_PRIORITY) == 0) {
2177                 stm_cmd_buf_post(priv, index);
2178         }
2179         TRACE_EXIT();
2180 }
2181
2182 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2183 static int
2184 stm_event_process(MPT_ADAPTER *ioc,
2185                   EventNotificationReply_t *rep)
2186 {
2187     MPT_STM_PRIV                *priv = mpt_stm_priv[ioc->id];
2188     EventDataScsi_t             *scsi_data;
2189     EventDataLinkStatus_t       *link_status_data;
2190     EventDataLoopState_t        *loop_state_data;
2191     EventDataLogout_t           *logout_data;
2192     EventDataSasPhyLinkStatus_t *sas_phy_link_status_data;
2193     int                         id;
2194     int                         i;
2195     int                         ioc_status;
2196     int                         event;
2197     int                         rate;
2198
2199         TRACE_ENTRY();
2200     if (priv == NULL) {
2201                 return (1);
2202         }
2203
2204     ioc_status = le16_to_cpu(rep->IOCStatus);
2205     event = le32_to_cpu(rep->Event);
2206
2207         if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
2208                 printk("%s Event = %x, IOCLogInfo = %08x\n",
2209                                 ioc->name, event, le32_to_cpu(rep->IOCLogInfo));
2210         }
2211
2212     switch (event) {
2213         case MPI_EVENT_NONE:
2214         case MPI_EVENT_LOG_DATA:
2215         case MPI_EVENT_STATE_CHANGE:
2216         case MPI_EVENT_UNIT_ATTENTION:
2217         case MPI_EVENT_EVENT_CHANGE:
2218         case MPI_EVENT_INTEGRATED_RAID:
2219         case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
2220         case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
2221         case MPI_EVENT_QUEUE_FULL:
2222         case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
2223         case MPI_EVENT_SAS_SES:
2224         case MPI_EVENT_PERSISTENT_TABLE_FULL:
2225         case MPI_EVENT_SAS_DISCOVERY_ERROR:
2226             break;
2227
2228         case MPI_EVENT_RESCAN:
2229             printk("%s Rescan\n", ioc->name);
2230             break;
2231
2232         case MPI_EVENT_IOC_BUS_RESET:
2233             scsi_data = (EventDataScsi_t *)rep->Data;
2234             printk("%s IOC Bus Reset on port %d\n",
2235                    ioc->name, scsi_data->BusPort);
2236             break;
2237
2238         case MPI_EVENT_EXT_BUS_RESET:
2239             scsi_data = (EventDataScsi_t *)rep->Data;
2240             printk("%s Ext Bus Reset on port %d\n",
2241                    ioc->name, scsi_data->BusPort);
2242             break;
2243
2244         case MPI_EVENT_LINK_STATUS_CHANGE:
2245             link_status_data = (EventDataLinkStatus_t *)rep->Data;
2246             printk("%s Link is now %s\n",
2247                    ioc->name, link_status_data->State ? "Up" : "Down");
2248             break;
2249
2250         case MPI_EVENT_LOGOUT:
2251             logout_data = (EventDataLogout_t *)rep->Data;
2252             id = le32_to_cpu(logout_data->NPortID);
2253             break;
2254
2255         case MPI_EVENT_LOOP_STATE_CHANGE:
2256             loop_state_data = (EventDataLoopState_t *)rep->Data;
2257             if (loop_state_data->Type == MPI_EVENT_LOOP_STATE_CHANGE_LIP) {
2258                 printk("%s LIP Reset\n", ioc->name);
2259                 break;
2260             } /* fall-through */
2261
2262         case MPI_EVENT_SAS_PHY_LINK_STATUS:
2263             sas_phy_link_status_data = (EventDataSasPhyLinkStatus_t *)rep->Data;
2264             rate = (sas_phy_link_status_data->LinkRates &
2265                     MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
2266                      MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
2267             printk("%s Phy %d Handle %x is now %s\n",
2268                    ioc->name, sas_phy_link_status_data->PhyNum,
2269                    le16_to_cpu(sas_phy_link_status_data->DevHandle),
2270                    rate == MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN ? "offline" :
2271                    rate == MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED ? "disabled" :
2272                    rate == MPI_EVENT_SAS_PLS_LR_RATE_1_5 ? "online at 1.5 Gb" :
2273                    rate == MPI_EVENT_SAS_PLS_LR_RATE_3_0 ? "online at 3.0 Gb" :
2274                    "unknown");
2275             break;
2276
2277         default:
2278             printk("%s event = %d, ack = %d, length = %d\n",
2279                    ioc->name, le32_to_cpu(rep->Event),
2280                    rep->AckRequired, le16_to_cpu(rep->EventDataLength));
2281             for (i = 0; i < le16_to_cpu(rep->EventDataLength); i++) {
2282                 printk("%s data[%d] = %08x\n",
2283                        ioc->name, i, le32_to_cpu(rep->Data[i]));
2284             }
2285             break;
2286     }
2287
2288     if (event == MPI_EVENT_EXT_BUS_RESET) {
2289 #if 0
2290         if (IsScsi(priv)) {
2291             memset(priv->luns->drop, 0, sizeof(priv->luns->drop));
2292         }
2293 #endif
2294     }
2295         TRACE_EXIT();
2296
2297     return (1);
2298 }
2299
2300 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2301 static int
2302 stm_reset_process(MPT_ADAPTER *ioc, int phase)
2303 {
2304     MPT_STM_PRIV        *priv = mpt_stm_priv[ioc->id];
2305     int                 i;
2306
2307         TRACE_ENTRY();
2308         if (priv == NULL)
2309                 return (1);
2310
2311         if (phase == MPT_IOC_PRE_RESET) {
2312                 printk(KERN_ERR MYNAM ":%s IOC will be reset\n",
2313                                 ioc->name);
2314                 priv->in_reset = 1;
2315                 priv->config_pending = 0;
2316                 for (i = 0; i < priv->num_cmd_buffers; i++)
2317                         priv->io_state[i] = 0;
2318         }
2319
2320         if (phase == MPT_IOC_POST_RESET) {
2321                 printk(KERN_ERR MYNAM ":%s IOC has been reset, restarting now\n",
2322                                 ioc->name);
2323                 mpt_stm_adapter_online(priv);
2324         }
2325
2326         TRACE_EXIT();
2327
2328     return (1);
2329 }
2330
2331 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2332 static void
2333 stm_link_service_reply(MPT_ADAPTER *ioc, LinkServiceBufferPostReply_t *rep)
2334 {
2335     MPT_STM_PRIV        *priv = mpt_stm_priv[ioc->id];
2336     FC_ELS              *fc_els_buf;
2337     int                 index;
2338     int                 rctl;
2339     int                 type;
2340     int                 sid;
2341     int                 did;
2342     int                 command;
2343     int                 i;
2344     u32                 wwnnh;
2345     u32                 wwnnl;
2346     u32                 wwpnh;
2347     u32                 wwpnl;
2348     int                 ox_id;
2349     int                 rx_id;
2350     u32                 offset;
2351
2352         TRACE_ENTRY();
2353     index = le32_to_cpu(rep->TransactionContext);
2354     fc_els_buf = &priv->hw->fc_link_serv_buf[index];
2355
2356     rctl =
2357         (le32_to_cpu(rep->Rctl_Did) & MPI_FC_RCTL_MASK) >> MPI_FC_RCTL_SHIFT;
2358     type =
2359         (le32_to_cpu(rep->Type_Fctl) & MPI_FC_TYPE_MASK) >> MPI_FC_TYPE_SHIFT;
2360     sid =
2361         (le32_to_cpu(rep->Csctl_Sid) & MPI_FC_SID_MASK) >> MPI_FC_SID_SHIFT;
2362     did =
2363         (le32_to_cpu(rep->Rctl_Did) & MPI_FC_DID_MASK) >> MPI_FC_DID_SHIFT;
2364
2365     wwnnh = le32_to_cpu(rep->Wwn.NodeNameHigh);
2366     wwnnl = le32_to_cpu(rep->Wwn.NodeNameLow);
2367     wwpnh = le32_to_cpu(rep->Wwn.PortNameHigh);
2368     wwpnl = le32_to_cpu(rep->Wwn.PortNameLow);
2369
2370     ox_id = le16_to_cpu(rep->Oxid);
2371     rx_id = le16_to_cpu(rep->Rxid);
2372
2373     /*
2374      *  if this is a received PRLI/PRLO, respond by sending our own PRLI/PRLO
2375      */
2376     if (rctl == ELS && type == 0x01) {
2377         command = (be32_to_cpu(fc_els_buf->fc_els[0]) >> 24) & 0xff;
2378         switch (command) {
2379             case PRLI:
2380                 TRACE_DBG("%s: PRLI to %06x from %06x (wwn %08x%08x)",
2381                                 ioc->name, did, sid, wwpnh, wwpnl);
2382                 i = be32_to_cpu(fc_els_buf->fc_els[4]);
2383                 fc_els_buf->fc_els[0] = cpu_to_be32(0x02100014);
2384                 fc_els_buf->fc_els[1] = cpu_to_be32(0x08002100);
2385                 fc_els_buf->fc_els[2] = cpu_to_be32(0x00000000);
2386                 fc_els_buf->fc_els[3] = cpu_to_be32(0x00000000);
2387                 fc_els_buf->fc_els[4] = cpu_to_be32(0x00000012);
2388                 if (priv->fcp2_capable)
2389                     fc_els_buf->fc_els[4] |= cpu_to_be32(0x100);
2390                 priv->els_state[index] = PRLI;
2391                 stm_send_els(priv, rep, index, 20);
2392                 return;
2393
2394             case PRLO:
2395                 TRACE_DBG("%s: PRLO to %06x from %06x (wwn %08x%08x)",
2396                         ioc->name, did, sid, wwpnh, wwpnl);
2397                 fc_els_buf->fc_els[0] = cpu_to_be32(0x02100014);
2398                 fc_els_buf->fc_els[1] = cpu_to_be32(0x08000100);
2399                 fc_els_buf->fc_els[2] = cpu_to_be32(0x00000000);
2400                 fc_els_buf->fc_els[3] = cpu_to_be32(0x00000000);
2401                 fc_els_buf->fc_els[4] = cpu_to_be32(0x00000000);
2402                 priv->els_state[index] = PRLO;
2403                 stm_send_els(priv, rep, index, 20);
2404                 return;
2405
2406             case RSCN:
2407                 TRACE_DBG("%s: RSCN", ioc->name);
2408                 stm_link_serv_buf_post(priv, index);
2409                 return;
2410
2411             default:
2412                 TRACE_DBG("%s: ELS %02x to %06x from %06x (wwn %08x%08x)",
2413                         ioc->name, command, did, sid, wwpnh, wwpnl);
2414                 stm_link_serv_buf_post(priv, index);
2415                 return;
2416         }
2417     }
2418
2419     /*
2420      *  if this is a received ABTS, respond by aborting the I/O and then
2421      *  accepting it
2422      */
2423     if (rctl == ABTS && type == 0x00) {
2424         TRACE_DBG("%s: ABTS to %06x from %06x (wwn %08x%08x)",
2425                 ioc->name, did, sid, wwpnh, wwpnl);
2426         fc_els_buf->fc_els[0] = cpu_to_be32(0x00000000);
2427         fc_els_buf->fc_els[1] = cpu_to_be32((ox_id << 16) | (rx_id << 0));
2428         fc_els_buf->fc_els[2] = cpu_to_be32(0x0000ffff);
2429         rep->Rctl_Did += cpu_to_le32((BA_ACC - ABTS) << MPI_FC_RCTL_SHIFT);
2430         priv->els_state[index] = ABTS;
2431         stmapp_abts_process(priv, rx_id, rep, index);
2432         stm_send_els(priv, rep, index, 12);
2433         return;
2434     }
2435
2436     /*
2437      *  if this is a received SRR, respond by aborting any current TargetAssist
2438      *  or TargetStatusSend commands, accepting the SRR, and retransmitting the
2439      *  requested data or status
2440      */
2441     if (rctl == FC4LS && type == 0x08) {
2442         priv->els_state[index] = FC4LS;
2443         command = (be32_to_cpu(fc_els_buf->fc_els[0]) >> 24) & 0xff;
2444         switch (command) {
2445             case SRR:
2446                 TRACE_DBG("%s: SRR to %06x from %06x (wwn %08x%08x)",
2447                         ioc->name, did, sid, wwpnh, wwpnl);
2448                 rx_id = be32_to_cpu(fc_els_buf->fc_els[1]) & 0xffff;
2449                 /*
2450                  *  if the rx_id is out of range, reject this SRR with
2451                  *  "invalid OX_ID/RX_ID combination"
2452                  */
2453                 if (rx_id >= priv->num_cmd_buffers) {
2454                     fc_els_buf->fc_els[0] = cpu_to_be32(0x01000000);
2455                     fc_els_buf->fc_els[1] = cpu_to_be32(0x00090300);
2456                     stm_send_els(priv, rep, index, 8);
2457                     return;
2458                 }
2459                 i = (be32_to_cpu(fc_els_buf->fc_els[3]) >> 24) & 0xff;
2460                 /*
2461                  *  if the IU to retransmit is not a recognized IU, reject
2462                  *  this SRR with "logical error"
2463                  */
2464                 if (i != 1 && i != 5 && i != 7) {
2465                     fc_els_buf->fc_els[0] = cpu_to_be32(0x01000000);
2466                     fc_els_buf->fc_els[1] = cpu_to_be32(0x00030000);
2467                     stm_send_els(priv, rep, index, 8);
2468                     return;
2469                 }
2470                 offset = be32_to_cpu(fc_els_buf->fc_els[2]);
2471                 /*
2472                  *  go process this SRR further
2473                  *
2474                  *  make the call to stm_send_els when any request in progress
2475                  *  has been aborted
2476                  *
2477                  *  note that the address of the LinkServiceBufferPostReply
2478                  *  that's passed as a parameter to stmapp_abts_process CANNOT
2479                  *  BE REMEMBERED; its contents must be copied if the call to
2480                  *  stm_send_els will not be made synchronously
2481                  */
2482                 stmapp_srr_process(priv, rx_id, i, offset, rep, index);
2483                 return;
2484
2485             default:
2486                 TRACE_DBG("%s: FC4LS %02x to %06x from %06x (wwn %08x%08x)",
2487                         ioc->name, command, did, sid, wwpnh, wwpnl);
2488                 /*
2489                  *  the only FC4LS we recognize is SRR; all others get
2490                  *  rejected with "command not supported"
2491                  */
2492                 fc_els_buf->fc_els[0] = cpu_to_be32(0x01000000);
2493                 fc_els_buf->fc_els[1] = cpu_to_be32(0x000b0000);
2494                 stm_send_els(priv, rep, index, 8);
2495                 return;
2496         }
2497     }
2498
2499 #ifdef TRACING
2500         if(trace_mpi)
2501         {
2502                 u32 *p = (u32 *)rep;
2503                 int i;
2504
2505                 for (i = 0; i < 17; i++) {
2506                         TRACE(TRACE_MPI, "%s: fc_els[%02x] = %08x",
2507                                         ioc->name, i * 4, le32_to_cpu(p[i]));
2508                 }
2509         }
2510         if(trace_mpi)
2511         {
2512                 u32 *p = (u32 *)fc_els_buf;
2513                 int i;
2514
2515                 for (i = 0; i < (int)le32_to_cpu(rep->TransferLength) / 4; i++) {
2516                         TRACE(TRACE_MPI, "%s: fc_els_buf[%02x] = %08x",
2517                                         ioc->name, i * 4, le32_to_cpu(p[i]));
2518                 }
2519         }
2520 #endif
2521
2522     stm_link_serv_buf_post(priv, index);
2523         TRACE_EXIT();
2524 }
2525
2526 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2527 static void
2528 stm_link_service_rsp_reply(MPT_ADAPTER *ioc,
2529                            LinkServiceRspRequest_t *req,
2530                            LinkServiceRspReply_t *rep)
2531 {
2532     MPT_STM_PRIV        *priv = mpt_stm_priv[ioc->id];
2533     MPT_STM_SIMPLE      *sge_simple;
2534     int                 *p_index;
2535     int                 index;
2536     int                 sid;
2537     int                 did;
2538     int                 els;
2539     int                 init_index;
2540
2541         TRACE_ENTRY();
2542     sge_simple = (MPT_STM_SIMPLE *)&req->SGL;
2543     p_index = (int *)(sge_simple + 1);
2544     index = *p_index;
2545     els = priv->els_state[index];
2546
2547     sid = (le32_to_cpu(req->Csctl_Sid) & MPI_FC_SID_MASK) >> MPI_FC_SID_SHIFT;
2548     did = (le32_to_cpu(req->Rctl_Did) & MPI_FC_DID_MASK) >> MPI_FC_DID_SHIFT;
2549     init_index = le32_to_cpu(rep->InitiatorIndex);
2550     /*
2551      *  after our link service reponse has been sent, repost the link service
2552      *  buffer
2553      */
2554     priv->els_state[index] = 0;
2555     stm_link_serv_buf_post(priv, index);
2556         TRACE_EXIT();
2557 }
2558
2559 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2560 static void
2561 stm_cmd_buf_post(MPT_STM_PRIV *priv, int index)
2562 {
2563     MPT_ADAPTER *ioc = priv->ioc;
2564     TargetCmdBufferPostRequest_t *req;
2565     dma_addr_t  dma_addr;
2566
2567         TRACE_ENTRY();
2568         if (priv->exiting) {
2569                 priv->io_state[index] |= IO_STATE_POSTED;
2570                 return;
2571         }
2572
2573         if (IsSas(priv)) {
2574                 stm_cmd_buf_post_list(priv, index);
2575                 return;
2576         }
2577
2578     /*
2579      *  get a free message frame, and post a command buffer
2580      */
2581     req = (TargetCmdBufferPostRequest_t *)mpt_msg_frame_alloc(ioc,index);
2582     memset(req, 0, sizeof(*req));
2583
2584 #ifdef CMD_BUFFER_POST_FLAGS_HIGH_PRIORITY
2585         if (priv->io_state[index] & IO_STATE_HIGH_PRIORITY) {
2586                 req->BufferPostFlags = CMD_BUFFER_POST_FLAGS_HIGH_PRIORITY;
2587         }
2588 #else
2589         priv->io_state[index] &= ~IO_STATE_HIGH_PRIORITY;
2590 #endif
2591
2592     req->BufferCount = 1;
2593     req->Function = MPI_FUNCTION_TARGET_CMD_BUFFER_POST;
2594     req->BufferLength = sizeof(priv->hw->cmd_buf[index].cmd);
2595     req->Buffer[0].IoIndex = (u16)cpu_to_le16(index);
2596     dma_addr = priv->hw_dma +
2597         ((u8 *)priv->hw->cmd_buf[index].cmd - (u8 *)priv->hw);
2598     req->Buffer[0].u.PhysicalAddress64.Low = cpu_to_le32(dma_addr);
2599 #if MPT_STM_64_BIT_DMA
2600     req->Buffer[0].u.PhysicalAddress64.High = cpu_to_le32((u64)dma_addr>>32);
2601     req->BufferPostFlags = CMD_BUFFER_POST_FLAGS_64_BIT_ADDR;
2602 #endif
2603
2604     priv->io_state[index] |= IO_STATE_POSTED;
2605
2606 #ifdef TRACING
2607         if(trace_mpi) {
2608                 u32 *p = (u32 *)req;
2609                 int i;
2610
2611                 TRACE(TRACE_MPI, "%s: stm_cmd_buf_post %d", ioc->name, index);
2612                 for (i = 0; i < sizeof(*req) / 4; i++) {
2613                         TRACE(TRACE_MPI, "%s: req[%02x] = %08x",
2614                                         ioc->name, i * 4, le32_to_cpu(p[i]));
2615                 }
2616         }
2617 #endif
2618
2619         priv->current_mf[index] = NULL;
2620         if (priv->io_state[index] & IO_STATE_HIGH_PRIORITY) {
2621                 priv->io_state[index] &= ~IO_STATE_HIGH_PRIORITY;
2622                 mpt_send_handshake_request(stm_context, _IOC_ID,
2623                                 sizeof(*req), (u32 *)req _HS_SLEEP);
2624         } else {
2625                 mpt_put_msg_frame(stm_context, _IOC_ID, (MPT_FRAME_HDR *)req);
2626         }
2627
2628         TRACE_EXIT();
2629 }
2630
2631 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2632 static void
2633 stm_cmd_buf_post_base(MPT_STM_PRIV *priv,
2634                       int post_all)
2635 {
2636     MPT_ADAPTER                         *ioc = priv->ioc;
2637     TargetCmdBufferPostBaseRequest_t    *req;
2638     int                                 i;
2639     dma_addr_t                          dma_addr;
2640
2641         TRACE_ENTRY();
2642     req = (TargetCmdBufferPostBaseRequest_t *)mpt_msg_frame_alloc(ioc,-1);
2643     memset(req, 0, sizeof(*req));
2644
2645     if (post_all) {
2646         req->BufferPostFlags = CMD_BUFFER_POST_BASE_FLAGS_AUTO_POST_ALL;
2647     }
2648     req->Function = MPI_FUNCTION_TARGET_CMD_BUF_BASE_POST;
2649     req->TotalCmdBuffers = (u16)priv->num_cmd_buffers;
2650     req->CmdBufferLength = sizeof(priv->hw->cmd_buf[0].cmd);
2651     req->NextCmdBufferOffset = sizeof(priv->hw->cmd_buf[0]);
2652     dma_addr = priv->hw_dma +
2653         ((u8 *)priv->hw->cmd_buf[0].cmd - (u8 *)priv->hw);
2654     req->BaseAddressLow = cpu_to_le32(dma_addr);
2655 #if MPT_STM_64_BIT_DMA
2656     req->BaseAddressHigh = cpu_to_le32((u64)dma_addr>>32);
2657 #endif
2658
2659     if (post_all) {
2660         for (i = 0; i < priv->num_cmd_buffers; i++) {
2661             priv->io_state[i] |= IO_STATE_POSTED;
2662         }
2663     }
2664
2665 #ifdef TRACING
2666         if(trace_mpi)
2667         {
2668                 u32 *p = (u32 *)req;
2669                 int i;
2670
2671                 TRACE(TRACE_MPI, "%s: stm_cmd_buf_post_base", ioc->name);
2672                 for (i = 0; i < sizeof(*req) / 4; i++) {
2673                         TRACE(TRACE_MPI, "%s: req[%02x] = %08x",
2674                                         ioc->name, i * 4, le32_to_cpu(p[i]));
2675                 }
2676         }
2677 #endif
2678
2679     mpt_put_msg_frame(stm_context, _IOC_ID, (MPT_FRAME_HDR *)req);
2680
2681         TRACE_EXIT();
2682 }
2683
2684 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2685 static void
2686 stm_cmd_buf_post_list(MPT_STM_PRIV *priv,
2687                       int index)
2688 {
2689     MPT_ADAPTER                         *ioc = priv->ioc;
2690     TargetCmdBufferPostListRequest_t    *req;
2691
2692         TRACE_ENTRY();
2693     req = (TargetCmdBufferPostListRequest_t *)mpt_msg_frame_alloc(ioc,index);
2694     memset(req, 0, sizeof(*req));
2695
2696     req->Function = MPI_FUNCTION_TARGET_CMD_BUF_LIST_POST;
2697     req->CmdBufferCount = 1;
2698     req->IoIndex[0] = (u16)cpu_to_le16(index);
2699
2700     priv->io_state[index] |= IO_STATE_POSTED;
2701
2702 #ifdef TRACING
2703         if(trace_mpi)
2704         {
2705                 u32 *p = (u32 *)req;
2706                 int i;
2707
2708                 TRACE(TRACE_MPI, "%s: stm_cmd_buf_post_list %d", ioc->name, index);
2709                 for (i = 0; i < sizeof(*req) / 4; i++) {
2710                         TRACE(TRACE_MPI, "%s: req[%02x] = %08x",
2711                                         ioc->name, i * 4, le32_to_cpu(p[i]));
2712                 }
2713         }
2714 #endif
2715
2716         mpt_put_msg_frame(stm_context, _IOC_ID, (MPT_FRAME_HDR *)req);
2717         TRACE_EXIT();
2718 }
2719
2720 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2721 static void
2722 stm_link_serv_buf_post(MPT_STM_PRIV *priv, int index)
2723 {
2724     MPT_ADAPTER                         *ioc = priv->ioc;
2725     LinkServiceBufferPostRequest_t      *req;
2726     SGETransaction32_t                  *sge_trans;
2727     MPT_STM_SIMPLE                      *sge_simple;
2728     dma_addr_t                          dma_addr;
2729
2730         TRACE_ENTRY();
2731     req = (LinkServiceBufferPostRequest_t *)mpt_msg_frame_alloc(ioc,index);
2732     memset(req, 0, sizeof(*req));
2733
2734     req->BufferCount = 1;
2735     req->Function = MPI_FUNCTION_FC_LINK_SRVC_BUF_POST;
2736     sge_trans = (SGETransaction32_t *)&req->SGL;
2737     sge_trans->ContextSize = 4;
2738     sge_trans->DetailsLength = 0;
2739     sge_trans->Flags = 0;
2740     sge_trans->TransactionContext[0] = cpu_to_le32(index);
2741     sge_simple = (MPT_STM_SIMPLE *)&sge_trans->TransactionDetails[0];
2742     sge_simple->FlagsLength = cpu_to_le32(sizeof(FC_ELS) |
2743         MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2744                           MPI_SGE_FLAGS_LAST_ELEMENT |
2745                           MPI_SGE_FLAGS_END_OF_BUFFER |
2746                           MPI_SGE_FLAGS_END_OF_LIST |
2747                           MPI_SGE_FLAGS_MPT_STM_ADDRESSING |
2748                           MPI_SGE_FLAGS_HOST_TO_IOC));
2749     dma_addr = priv->hw_dma +
2750         ((u8 *)priv->hw->fc_link_serv_buf[index].fc_els - (u8 *)priv->hw);
2751     stm_set_dma_addr(sge_simple->Address, dma_addr);
2752
2753 #ifdef TRACING
2754         if(trace_mpi)
2755         {
2756                 u32 *p = (u32 *)req;
2757                 int i;
2758
2759                 TRACE(TRACE_MPI, "%s: stm_link_serv_buf_post %d", ioc->name, index);
2760                 for (i = 0; i < sizeof(*req) / 4; i++) {
2761                         TRACE(TRACE_MPI, "%s: req[%02x] = %08x",
2762                                         ioc->name, i * 4, le32_to_cpu(p[i]));
2763                 }
2764         }
2765 #endif
2766         priv->current_mf[index] = NULL;
2767     mpt_put_msg_frame(stm_context, _IOC_ID, (MPT_FRAME_HDR *)req);
2768         TRACE_EXIT();
2769 }
2770
2771 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2772 static int
2773 stm_send_target_status(MPT_STM_PRIV *priv,
2774                        u32 reply_word, int index, int flags, int lun, int tag)
2775 {
2776     MPT_ADAPTER                 *ioc = priv->ioc;
2777     TargetStatusSendRequest_t   *req;
2778     MPT_STM_SIMPLE              *sge_simple;
2779     CMD                         *cmd;
2780     int                         length;
2781     int                         status;
2782     int                         init_index;
2783         dma_addr_t                      dma_addr;
2784         MPT_FRAME_HDR *mf = priv->current_mf[index];
2785
2786         TRACE_ENTRY();
2787     if (priv->io_state[index] & IO_STATE_DATA_SENT) {
2788                 priv->current_mf[index] = NULL;
2789         }
2790     req = (TargetStatusSendRequest_t *)mpt_msg_frame_alloc(ioc,index);
2791     memset(req, 0, sizeof(*req));
2792
2793     if (priv->exiting) {
2794         flags &= ~TARGET_ASSIST_FLAGS_REPOST_CMD_BUFFER;
2795         priv->io_state[index] &= ~IO_STATE_AUTO_REPOST;
2796     }
2797
2798     if (priv->io_state[index] & IO_STATE_HIGH_PRIORITY) {
2799         flags |= TARGET_STATUS_SEND_FLAGS_HIGH_PRIORITY;
2800         flags |= TARGET_STATUS_SEND_FLAGS_REPOST_CMD_BUFFER;
2801         priv->io_state[index] |= IO_STATE_AUTO_REPOST;
2802     }
2803
2804     if (priv->fcp2_capable/* && priv->initiators != NULL*/) {
2805         init_index = GET_INITIATOR_INDEX(reply_word);
2806         /*init = priv->initiators[init_index];
2807         if (init != NULL && init->confirm_capable) {
2808             flags |= TARGET_STATUS_SEND_FLAGS_CONFIRMED;
2809         }*/
2810     }
2811
2812     cmd = &priv->hw->cmd_buf[index];
2813
2814     if (flags & TARGET_STATUS_SEND_FLAGS_AUTO_GOOD_STATUS) {
2815         length = 0;
2816         req->StatusCode = 0;
2817     } else {
2818         length = 0;
2819         if (IsScsi(priv)) {
2820             SCSI_RSP    *rsp = (SCSI_RSP *)cmd->rsp;
2821
2822             length += sizeof(*rsp);
2823             length -= sizeof(rsp->SenseData);
2824             status = rsp->Status;
2825             if (rsp->Valid & SCSI_SENSE_LEN_VALID) {
2826                 length += be32_to_cpu(rsp->SenseDataListLength);
2827                 init_index = GET_INITIATOR_INDEX(reply_word);
2828                 /*
2829                  *  try to avoid a SCSI firmware bug by not using Auto Repost
2830                  *  here, unless required (High Priority requires it)
2831                  */
2832                 if (!(priv->io_state[index] & IO_STATE_HIGH_PRIORITY)) {
2833                     flags &= ~TARGET_STATUS_SEND_FLAGS_REPOST_CMD_BUFFER;
2834                     priv->io_state[index] &= ~IO_STATE_AUTO_REPOST;
2835                 }
2836             }
2837             if (rsp->Valid & SCSI_RSP_LEN_VALID) {
2838                 length += be32_to_cpu(rsp->PktFailuresListLength);
2839             }
2840         } else if (IsSas(priv)) {
2841             SSP_RSP     *rsp = (SSP_RSP *)cmd->rsp;
2842
2843             length += sizeof(*rsp);
2844             length -= sizeof(rsp->ResponseSenseData);
2845             status = rsp->Status;
2846             if (rsp->DataPres & SSP_SENSE_LEN_VALID) {
2847                 length += be32_to_cpu(rsp->SenseDataLength);
2848             }
2849             if (rsp->DataPres & SSP_RSP_LEN_VALID) {
2850                 length += be32_to_cpu(rsp->ResponseDataLength);
2851             }
2852         } else {
2853             FCP_RSP     *rsp = (FCP_RSP *)cmd->rsp;
2854
2855             length += sizeof(*rsp);
2856             length -= sizeof(rsp->FcpSenseData) + sizeof(rsp->FcpResponseData);
2857             status = rsp->FcpStatus;
2858             if (flags & TARGET_STATUS_SEND_FLAGS_CONFIRMED) {
2859                 rsp->FcpFlags |= FCP_REQUEST_CONFIRM;
2860             }
2861             if (rsp->FcpFlags & FCP_SENSE_LEN_VALID) {
2862                 length += be32_to_cpu(rsp->FcpSenseLength);
2863             }
2864             if (rsp->FcpFlags & FCP_RSP_LEN_VALID) {
2865                 length += be32_to_cpu(rsp->FcpResponseLength);
2866                 /* FCP_RSP_LEN_VALID will only be set for Task Mgmt responses */
2867                 /* and Task Mgmt responses can't be confirmed */
2868                 rsp->FcpFlags &= ~FCP_REQUEST_CONFIRM;
2869                 flags &= ~TARGET_STATUS_SEND_FLAGS_CONFIRMED;
2870             }
2871         }
2872         req->StatusCode = (u8)status;
2873     }
2874
2875     req->StatusFlags = (u8)flags;
2876     req->Function = MPI_FUNCTION_TARGET_STATUS_SEND;
2877     req->QueueTag = (u16)tag;
2878     req->ReplyWord = cpu_to_le32(reply_word);
2879     req->LUN[0] = (u8)(lun >> 8);
2880     req->LUN[1] = (u8)lun;
2881     if (length != 0) {
2882         sge_simple = (MPT_STM_SIMPLE *)&req->StatusDataSGE;
2883         sge_simple->FlagsLength = cpu_to_le32(length |
2884             MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2885                               MPI_SGE_FLAGS_LAST_ELEMENT |
2886                               MPI_SGE_FLAGS_END_OF_BUFFER |
2887                               MPI_SGE_FLAGS_END_OF_LIST |
2888                               MPI_SGE_FLAGS_MPT_STM_ADDRESSING |
2889                               MPI_SGE_FLAGS_HOST_TO_IOC));
2890         dma_addr = priv->hw_dma +
2891             ((u8 *)priv->hw->cmd_buf[index].rsp - (u8 *)priv->hw);
2892         stm_set_dma_addr(sge_simple->Address, dma_addr);
2893     }
2894
2895     /*
2896      *  there's a limitation here -- if target data is outstanding, we must
2897      *  wait for it to finish before we send the target status
2898      */
2899         if (priv->io_state[index] & IO_STATE_DATA_SENT) {
2900                 priv->current_mf[index] = mf;
2901                 priv->status_deferred_mf[index] = (MPT_FRAME_HDR *)req;
2902                 priv->io_state[index] |= IO_STATE_STATUS_DEFERRED;
2903                 TRACE_EXIT_RES(1);
2904                 return (1);
2905         }
2906         priv->io_state[index] |= IO_STATE_STATUS_SENT;
2907
2908 #ifdef TRACING
2909         if(trace_mpi)
2910         {
2911                 u32 *p = (u32 *)req;
2912                 int i;
2913
2914                 TRACE(TRACE_MPI, "%s: stm_send_target_status %d",
2915                                 ioc->name, index);
2916                 for (i = 0; i < sizeof(*req) / 4; i++) {
2917                         TRACE(TRACE_MPI, "%s: req[%02x] = %08x",
2918                                         ioc->name, i * 4, le32_to_cpu(p[i]));
2919                 }
2920         }
2921 #endif
2922
2923         if (priv->io_state[index] & IO_STATE_HIGH_PRIORITY) {
2924                 mpt_send_handshake_request(stm_context, _IOC_ID,
2925                                 sizeof(*req), (u32 *)req _HS_SLEEP);
2926         } else {
2927                 mpt_put_msg_frame(stm_context, _IOC_ID, (MPT_FRAME_HDR *)req);
2928         }
2929         TRACE_EXIT_RES(1);
2930     return (1);
2931 }
2932
2933 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2934 static void
2935 stm_send_els(MPT_STM_PRIV *priv,
2936              LinkServiceBufferPostReply_t *rep, int index, int length)
2937 {
2938     MPT_ADAPTER                 *ioc = priv->ioc;
2939     LinkServiceRspRequest_t     *req;
2940     MPT_STM_SIMPLE              *sge_simple;
2941     int                         *p_index;
2942     dma_addr_t                  dma_addr;
2943
2944         TRACE_ENTRY();
2945     req = (LinkServiceRspRequest_t *)mpt_msg_frame_alloc(ioc,index);
2946     memset(req, 0, sizeof(*req));
2947
2948     req->RspLength = (u8)length;
2949     req->Function = MPI_FUNCTION_FC_LINK_SRVC_RSP;
2950     memcpy((u8 *)req + 0x0c, (u8 *)rep + 0x1c, 24);
2951     sge_simple = (MPT_STM_SIMPLE *)&req->SGL;
2952     sge_simple->FlagsLength = cpu_to_le32(length |
2953         MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2954                           MPI_SGE_FLAGS_LAST_ELEMENT |
2955                           MPI_SGE_FLAGS_END_OF_BUFFER |
2956                           MPI_SGE_FLAGS_END_OF_LIST |
2957                           MPI_SGE_FLAGS_MPT_STM_ADDRESSING |
2958                           MPI_SGE_FLAGS_HOST_TO_IOC));
2959     dma_addr = priv->hw_dma +
2960         ((u8 *)priv->hw->fc_link_serv_buf[index].fc_els - (u8 *)priv->hw);
2961     stm_set_dma_addr(sge_simple->Address, dma_addr);
2962     p_index = (int *)(sge_simple + 1);
2963     *p_index = index;
2964
2965 #ifdef TRACING
2966         if(trace_mpi)
2967         {
2968                 u32 *p = (u32 *)req;
2969                 int i;
2970
2971                 TRACE(TRACE_MPI, "%s: stm_send_els %d", ioc->name, index);
2972                 for (i = 0; i < sizeof(*req) / 4; i++) {
2973                         TRACE(TRACE_MPI, "%s: req[%02x] = %08x", 
2974                                         ioc->name, i * 4, le32_to_cpu(p[i]));
2975                 }
2976         }
2977 #endif
2978         priv->current_mf[index] = NULL;
2979     mpt_put_msg_frame(stm_context, _IOC_ID, (MPT_FRAME_HDR *)req);
2980         TRACE_EXIT();
2981 }
2982
2983 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2984 static int
2985 stm_port_enable(MPT_STM_PRIV *priv)
2986 {
2987     MPT_ADAPTER         *ioc = priv->ioc;
2988     PortEnable_t        *req;
2989         int ret;
2990
2991         TRACE_ENTRY();
2992     req = (PortEnable_t *)mpt_msg_frame_alloc(ioc,-1);
2993     memset(req, 0, sizeof(*req));
2994
2995     req->Function = MPI_FUNCTION_PORT_ENABLE;
2996
2997     priv->port_enable_pending = 1;
2998
2999     mpt_put_msg_frame(stm_context, _IOC_ID, (MPT_FRAME_HDR *)req);
3000
3001     ret = stm_wait_for(priv, &priv->port_enable_pending, 60, NO_SLEEP);
3002
3003         TRACE_EXIT_RES(ret);
3004
3005         return ret;
3006 }
3007
3008 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3009 static int
3010 stm_target_mode_abort_command(MPT_STM_PRIV *priv,
3011                               u32 reply_word, int index)
3012 {
3013     MPT_ADAPTER         *ioc = priv->ioc;
3014     TargetModeAbort_t   *req;
3015
3016         TRACE_ENTRY();
3017     req = (TargetModeAbort_t *)mpt_msg_frame_alloc(ioc,index);
3018     memset(req, 0, sizeof(*req));
3019
3020     req->AbortType = TARGET_MODE_ABORT_TYPE_EXACT_IO;
3021     req->Function = MPI_FUNCTION_TARGET_MODE_ABORT;
3022     req->ReplyWord = cpu_to_le32(reply_word);
3023
3024     priv->io_state[index] |= IO_STATE_ABORTED;
3025
3026         if (IsScsi(priv)) {
3027                 mpt_send_handshake_request(stm_context, _IOC_ID,
3028                                 sizeof(*req), (u32 *)req _HS_SLEEP);
3029         } else {
3030                 mpt_put_msg_frame(stm_context, _IOC_ID, (MPT_FRAME_HDR *)req);
3031         }
3032         TRACE_EXIT();
3033
3034     return (0);
3035 }
3036
3037 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3038 static int
3039 stm_target_mode_abort_request(MPT_STM_PRIV *priv,
3040                               u32 reply_word,
3041                               u32 msg_context,
3042                               int index)
3043 {
3044     MPT_ADAPTER         *ioc = priv->ioc;
3045     TargetModeAbort_t   *req;
3046
3047         TRACE_ENTRY();
3048     req = (TargetModeAbort_t *)mpt_msg_frame_alloc(ioc,index);
3049     memset(req, 0, sizeof(*req));
3050
3051     req->AbortType = TARGET_MODE_ABORT_TYPE_EXACT_IO_REQUEST;
3052     req->Function = MPI_FUNCTION_TARGET_MODE_ABORT;
3053     req->ReplyWord = cpu_to_le32(reply_word);
3054     req->MsgContextToAbort = cpu_to_le32(msg_context);
3055
3056     priv->io_state[index] |= IO_STATE_REQUEST_ABORTED;
3057
3058         if (IsScsi(priv)) {
3059                 mpt_send_handshake_request(stm_context, _IOC_ID,
3060                                 sizeof(*req), (u32 *)req _HS_SLEEP);
3061         } else {
3062                 mpt_put_msg_frame(stm_context, _IOC_ID, (MPT_FRAME_HDR *)req);
3063         }
3064         TRACE_EXIT();
3065
3066     return (0);
3067 }
3068
3069 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3070 static int
3071 stm_target_mode_abort_all(MPT_STM_PRIV *priv)
3072 {
3073     MPT_ADAPTER         *ioc = priv->ioc;
3074     TargetModeAbort_t   *req;
3075         int ret;
3076         TRACE_ENTRY();
3077
3078     req = (TargetModeAbort_t *)mpt_msg_frame_alloc(ioc,-1);
3079     memset(req, 0, sizeof(*req));
3080
3081     req->AbortType = TARGET_MODE_ABORT_TYPE_ALL_CMD_BUFFERS;
3082     req->Function = MPI_FUNCTION_TARGET_MODE_ABORT;
3083
3084     priv->target_mode_abort_pending = 1;
3085
3086         if (IsScsi(priv)) {
3087                 mpt_send_handshake_request(stm_context, _IOC_ID,
3088                                 sizeof(*req), (u32 *)req _HS_SLEEP);
3089         } else {
3090                 mpt_put_msg_frame(stm_context, _IOC_ID, (MPT_FRAME_HDR *)req);
3091         }
3092
3093     ret = stm_wait_for(priv, &priv->target_mode_abort_pending, 60, NO_SLEEP);
3094         TRACE_EXIT_RES(ret);
3095
3096         return ret;
3097 }
3098
3099 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3100 static int
3101 stm_target_mode_abort(MPT_STM_PRIV *priv)
3102 {
3103 #ifdef TRACING
3104     MPT_ADAPTER         *ioc = priv->ioc;
3105 #endif
3106     int                 i;
3107     int                 n;
3108
3109         TRACE_ENTRY();
3110         while (1) {
3111                 n = 0;
3112                 for (i = 0; i< priv->num_cmd_buffers; i++) {
3113                         if (priv->io_state[i] & IO_STATE_AUTO_REPOST) {
3114                                 n++;
3115                         }
3116                 }
3117
3118                 if (n == 0)
3119                         break;
3120
3121                 TRACE_DBG("%s: %d out of %d commands being auto-reposted, waiting...",
3122                                 ioc->name, n, priv->num_cmd_buffers);
3123                 stm_wait(priv, 10, CAN_SLEEP);
3124         }
3125
3126         while (1) {
3127                 stm_target_mode_abort_all(priv);
3128
3129                 n = 0;
3130                 for (i = 0; i< priv->num_cmd_buffers; i++) {
3131                         if (priv->io_state[i] & IO_STATE_POSTED) {
3132                                 n++;
3133                         }
3134                 }
3135
3136                 if (n == priv->num_cmd_buffers)
3137                         break;
3138
3139                 TRACE_DBG("%s: %d out of %d commands still active, waiting...",
3140                                 ioc->name, n, priv->num_cmd_buffers);
3141                 stm_wait(priv, 10, CAN_SLEEP);
3142         }
3143
3144         TRACE_EXIT();
3145     return (0);
3146 }
3147
3148 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3149 static int
3150 stm_link_serv_abort(MPT_STM_PRIV *priv)
3151 {
3152     MPT_ADAPTER         *ioc = priv->ioc;
3153     FcAbortRequest_t    *req;
3154         int ret;
3155
3156         TRACE_ENTRY();
3157
3158     req = (FcAbortRequest_t *)mpt_msg_frame_alloc(ioc,-1);
3159     memset(req, 0, sizeof(*req));
3160
3161     req->AbortType = FC_ABORT_TYPE_ALL_FC_BUFFERS;
3162     req->Function = MPI_FUNCTION_FC_ABORT;
3163
3164     priv->link_serv_abort_pending = 1;
3165
3166     mpt_put_msg_frame(stm_context, _IOC_ID, (MPT_FRAME_HDR *)req);
3167
3168     ret = stm_wait_for(priv, &priv->link_serv_abort_pending, 60, NO_SLEEP);
3169
3170         TRACE_EXIT_RES(ret);
3171
3172         return ret;
3173 }
3174
3175 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3176 static int
3177 stm_reset_link(MPT_STM_PRIV *priv)
3178 {
3179     MPT_ADAPTER                 *ioc = priv->ioc;
3180     FcPrimitiveSendRequest_t    *req;
3181         int ret;
3182
3183         TRACE_ENTRY();
3184     req = (FcPrimitiveSendRequest_t *)mpt_msg_frame_alloc(ioc,-1);
3185     memset(req, 0, sizeof(*req));
3186
3187     req->SendFlags = MPI_FC_PRIM_SEND_FLAGS_RESET_LINK;
3188     req->Function = MPI_FUNCTION_FC_PRIMITIVE_SEND;
3189
3190     priv->fc_primitive_send_pending = 1;
3191
3192     mpt_put_msg_frame(stm_context, _IOC_ID, (MPT_FRAME_HDR *)req);
3193
3194     ret = stm_wait_for(priv, &priv->fc_primitive_send_pending, 60, NO_SLEEP);
3195         TRACE_EXIT_RES(ret);
3196
3197         return ret;
3198 }
3199 #if 0
3200 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3201 static int
3202 stm_login_port(MPT_STM_PRIV *priv, int port_id, int sleep)
3203 {
3204     MPT_ADAPTER                 *ioc = priv->ioc;
3205     ExLinkServiceSendRequest_t  *req;
3206     MPT_STM_SIMPLE              *sge_simple;
3207     u32                         *buf;
3208     int                         len, ret;
3209     dma_addr_t                  dma_addr;
3210
3211         TRACE_ENTRY();
3212     req = (ExLinkServiceSendRequest_t *)mpt_msg_frame_alloc(ioc,index);
3213     memset(req, 0, sizeof(*req));
3214
3215     req->Function = MPI_FUNCTION_FC_EX_LINK_SRVC_SEND;
3216     req->MsgFlags_Did = cpu_to_le32(port_id);
3217     req->ElsCommandCode = cpu_to_le32(PLOGI);
3218
3219     len = 29 * 4;
3220     buf = priv->hw->exlink_buf;
3221     memset(buf, 0, len);
3222
3223     buf[0] = cpu_to_be32(PLOGI << 24);
3224     /*
3225      *  the firmware builds the rest of the PLOGI payload
3226      */
3227
3228     sge_simple = (MPT_STM_SIMPLE *)&req->SGL;
3229     sge_simple->FlagsLength = cpu_to_le32(len |
3230         MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT |
3231                           MPI_SGE_FLAGS_END_OF_BUFFER |
3232                           MPI_SGE_FLAGS_MPT_STM_ADDRESSING |
3233                           MPI_SGE_FLAGS_HOST_TO_IOC));
3234     dma_addr = priv->hw_dma + ((u8 *)priv->hw->exlink_buf - (u8 *)priv->hw);
3235     stm_set_dma_addr(sge_simple->Address, dma_addr);
3236     sge_simple++;
3237     sge_simple->FlagsLength = cpu_to_le32(len |
3238         MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT |
3239                           MPI_SGE_FLAGS_LAST_ELEMENT |
3240                           MPI_SGE_FLAGS_END_OF_BUFFER |
3241                           MPI_SGE_FLAGS_END_OF_LIST |
3242                           MPI_SGE_FLAGS_MPT_STM_ADDRESSING |
3243                           MPI_SGE_FLAGS_IOC_TO_HOST));
3244     dma_addr = priv->hw_dma + ((u8 *)priv->hw->exlink_buf - (u8 *)priv->hw);
3245     stm_set_dma_addr(sge_simple->Address, dma_addr);
3246
3247     priv->ex_link_service_send_pending = 1;
3248
3249     mpt_put_msg_frame(stm_context, _IOC_ID, mf);
3250
3251     if (stm_wait_for(priv, &priv->ex_link_service_send_pending, 5, sleep) < 0)
3252         return (-1);
3253
3254     req = (ExLinkServiceSendRequest_t *)mpt_msg_frame_alloc(ioc,index);
3255     memset(req, 0, sizeof(*req));
3256
3257     req->Function = MPI_FUNCTION_FC_EX_LINK_SRVC_SEND;
3258     req->MsgFlags_Did = cpu_to_le32(port_id);
3259     req->ElsCommandCode = cpu_to_le32(PRLI);
3260
3261     len = 5 * 4;
3262     buf = priv->hw->exlink_buf;
3263     memset(buf, 0, len);
3264
3265     buf[0] = cpu_to_be32(0x00100014 | (PRLI << 24));
3266     buf[1] = cpu_to_be32(0x08002000);
3267     buf[2] = cpu_to_be32(0x00000000);
3268     buf[3] = cpu_to_be32(0x00000000);
3269     buf[4] = cpu_to_be32(0x000000b2);
3270
3271     sge_simple = (MPT_STM_SIMPLE *)&req->SGL;
3272     sge_simple->FlagsLength = cpu_to_le32(len |
3273         MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT |
3274                           MPI_SGE_FLAGS_END_OF_BUFFER |
3275                           MPI_SGE_FLAGS_MPT_STM_ADDRESSING |
3276                           MPI_SGE_FLAGS_HOST_TO_IOC));
3277     dma_addr = priv->hw_dma + ((u8 *)priv->hw->exlink_buf - (u8 *)priv->hw);
3278     stm_set_dma_addr(sge_simple->Address, dma_addr);
3279     sge_simple++;
3280     sge_simple->FlagsLength = cpu_to_le32(len |
3281         MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT |
3282                           MPI_SGE_FLAGS_LAST_ELEMENT |
3283                           MPI_SGE_FLAGS_END_OF_BUFFER |
3284                           MPI_SGE_FLAGS_END_OF_LIST |
3285                           MPI_SGE_FLAGS_MPT_STM_ADDRESSING |
3286                           MPI_SGE_FLAGS_IOC_TO_HOST));
3287     dma_addr = priv->hw_dma + ((u8 *)priv->hw->exlink_buf - (u8 *)priv->hw);
3288     stm_set_dma_addr(sge_simple->Address, dma_addr);
3289
3290     priv->ex_link_service_send_pending = 1;
3291
3292     mpt_put_msg_frame(stm_context, _IOC_ID, mf);
3293
3294     ret = stm_wait_for(priv, &priv->ex_link_service_send_pending, 5, sleep);
3295
3296         TRACE_EXIT_RES(ret);
3297
3298         return ret;
3299 }
3300
3301 static int
3302 stm_logout_port(MPT_STM_PRIV *priv,
3303                 int port_id, int sleep)
3304 {
3305     MPT_ADAPTER                 *ioc = priv->ioc;
3306     ExLinkServiceSendRequest_t  *req;
3307     MPT_STM_SIMPLE              *sge_simple;
3308     u32                         *buf;
3309     int                         len, ret;
3310     dma_addr_t                  dma_addr;
3311
3312         TRACE_ENTRY();
3313     req = (ExLinkServiceSendRequest_t *)mpt_msg_frame_alloc(ioc,index);
3314     memset(req, 0, sizeof(*req));
3315
3316     req->Function = MPI_FUNCTION_FC_EX_LINK_SRVC_SEND;
3317     req->MsgFlags_Did = cpu_to_le32(port_id);
3318     req->ElsCommandCode = cpu_to_le32(LOGO);
3319
3320     len = 4 * 4;
3321     buf = priv->hw->exlink_buf;
3322     memset(buf, 0, len);
3323
3324     buf[0] = cpu_to_be32(LOGO << 24);
3325     /*
3326      *  the firmware builds the rest of the LOGO payload
3327      */
3328
3329     sge_simple = (MPT_STM_SIMPLE *)&req->SGL;
3330     sge_simple->FlagsLength = cpu_to_le32(len |
3331         MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT |
3332                           MPI_SGE_FLAGS_END_OF_BUFFER |
3333                           MPI_SGE_FLAGS_MPT_STM_ADDRESSING |
3334                           MPI_SGE_FLAGS_HOST_TO_IOC));
3335     dma_addr = priv->hw_dma + ((u8 *)priv->hw->exlink_buf - (u8 *)priv->hw);
3336     stm_set_dma_addr(sge_simple->Address, dma_addr);
3337     sge_simple++;
3338     sge_simple->FlagsLength = cpu_to_le32(len |
3339         MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT |
3340                           MPI_SGE_FLAGS_LAST_ELEMENT |
3341                           MPI_SGE_FLAGS_END_OF_BUFFER |
3342                           MPI_SGE_FLAGS_END_OF_LIST |
3343                           MPI_SGE_FLAGS_MPT_STM_ADDRESSING |
3344                           MPI_SGE_FLAGS_IOC_TO_HOST));
3345     dma_addr = priv->hw_dma + ((u8 *)priv->hw->exlink_buf - (u8 *)priv->hw);
3346     stm_set_dma_addr(sge_simple->Address, dma_addr);
3347
3348     priv->ex_link_service_send_pending = 1;
3349
3350     mpt_put_msg_frame(stm_context, _IOC_ID, mf);
3351
3352     ret = stm_wait_for(priv, &priv->ex_link_service_send_pending, 5, sleep);
3353
3354         TRACE_EXIT_RES(ret);
3355
3356         return ret;
3357 }
3358
3359 static int
3360 stm_process_logout_port(MPT_STM_PRIV *priv,
3361                         int port_id, int sleep)
3362 {
3363     MPT_ADAPTER                 *ioc = priv->ioc;
3364     ExLinkServiceSendRequest_t  *req;
3365     MPT_STM_SIMPLE              *sge_simple;
3366     u32                         *buf;
3367     int                         len, ret;
3368     dma_addr_t                  dma_addr;
3369
3370         TRACE_ENTRY();
3371     req = (ExLinkServiceSendRequest_t *)mpt_msg_frame_alloc(ioc,index);
3372     memset(req, 0, sizeof(*req));
3373
3374     req->Function = MPI_FUNCTION_FC_EX_LINK_SRVC_SEND;
3375     req->MsgFlags_Did = cpu_to_le32(port_id);
3376     req->ElsCommandCode = cpu_to_le32(PRLO);
3377
3378     len = 5 * 4;
3379     buf = priv->hw->exlink_buf;
3380     memset(buf, 0, len);
3381
3382     buf[0] = cpu_to_be32(0x00100014 | (PRLO << 24));
3383     buf[1] = cpu_to_be32(0x08002000);
3384     buf[2] = cpu_to_be32(0x00000000);
3385     buf[3] = cpu_to_be32(0x00000000);
3386     buf[4] = cpu_to_be32(0x00000000);
3387
3388     sge_simple = (MPT_STM_SIMPLE *)&req->SGL;
3389     sge_simple->FlagsLength = cpu_to_le32(len |
3390         MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT |
3391                           MPI_SGE_FLAGS_END_OF_BUFFER |
3392                           MPI_SGE_FLAGS_MPT_STM_ADDRESSING |
3393                           MPI_SGE_FLAGS_HOST_TO_IOC));
3394     dma_addr = priv->hw_dma + ((u8 *)priv->hw->exlink_buf - (u8 *)priv->hw);
3395     stm_set_dma_addr(sge_simple->Address, dma_addr);
3396     sge_simple++;
3397     sge_simple->FlagsLength = cpu_to_le32(len |
3398         MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT |
3399                           MPI_SGE_FLAGS_LAST_ELEMENT |
3400                           MPI_SGE_FLAGS_END_OF_BUFFER |
3401                           MPI_SGE_FLAGS_END_OF_LIST |
3402                           MPI_SGE_FLAGS_MPT_STM_ADDRESSING |
3403                           MPI_SGE_FLAGS_IOC_TO_HOST));
3404     dma_addr = priv->hw_dma + ((u8 *)priv->hw->exlink_buf - (u8 *)priv->hw);
3405     stm_set_dma_addr(sge_simple->Address, dma_addr);
3406
3407     priv->ex_link_service_send_pending = 1;
3408
3409     mpt_put_msg_frame(stm_context, _IOC_ID, mf);
3410
3411     ret = stm_wait_for(priv, &priv->ex_link_service_send_pending, 5, sleep);
3412
3413         TRACE_EXIT_RES(ret);
3414
3415         return ret;
3416 }
3417
3418 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3419 static int
3420 stm_get_hard_address(MPT_STM_PRIV *priv, int port_id, int *hard_address, 
3421                 int sleep)
3422 {
3423     MPT_ADAPTER                 *ioc = priv->ioc;
3424     ExLinkServiceSendRequest_t  *req;
3425     MPT_STM_SIMPLE              *sge_simple;
3426     u32                         *buf;
3427     int                         len;
3428     dma_addr_t                  dma_addr;
3429
3430         TRACE_ENTRY();
3431     req = (ExLinkServiceSendRequest_t *)mpt_msg_frame_alloc(ioc,index);
3432     memset(req, 0, sizeof(*req));
3433
3434     req->Function = MPI_FUNCTION_FC_EX_LINK_SRVC_SEND;
3435     req->MsgFlags_Did = cpu_to_le32(port_id);
3436     req->ElsCommandCode = cpu_to_le32(ADISC);
3437
3438     len = 7 * 4;
3439     buf = priv->hw->exlink_buf;
3440     memset(buf, 0, len);
3441
3442     buf[0] = cpu_to_be32(ADISC << 24);
3443     buf[1] = cpu_to_be32(0x00000000);   /* or get HardALPA from FCPortPage1 */
3444     buf[2] = cpu_to_be32(priv->wwpn.High);
3445     buf[3] = cpu_to_be32(priv->wwpn.Low);
3446     buf[4] = cpu_to_be32(priv->wwnn.High);
3447     buf[5] = cpu_to_be32(priv->wwnn.Low);
3448     buf[6] = cpu_to_be32(priv->port_id);
3449
3450     sge_simple = (MPT_STM_SIMPLE *)&req->SGL;
3451     sge_simple->FlagsLength = cpu_to_le32(len |
3452         MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT |
3453                           MPI_SGE_FLAGS_END_OF_BUFFER |
3454                           MPI_SGE_FLAGS_MPT_STM_ADDRESSING |
3455                           MPI_SGE_FLAGS_HOST_TO_IOC));
3456     dma_addr = priv->hw_dma + ((u8 *)priv->hw->exlink_buf - (u8 *)priv->hw);
3457     stm_set_dma_addr(sge_simple->Address, dma_addr);
3458     sge_simple++;
3459     sge_simple->FlagsLength = cpu_to_le32(len |
3460         MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_SIMPLE_ELEMENT |
3461                           MPI_SGE_FLAGS_LAST_ELEMENT |
3462                           MPI_SGE_FLAGS_END_OF_BUFFER |
3463                           MPI_SGE_FLAGS_END_OF_LIST |
3464                           MPI_SGE_FLAGS_MPT_STM_ADDRESSING |
3465                           MPI_SGE_FLAGS_IOC_TO_HOST));
3466     dma_addr = priv->hw_dma + ((u8 *)priv->hw->exlink_buf - (u8 *)priv->hw);
3467     stm_set_dma_addr(sge_simple->Address, dma_addr);
3468
3469     priv->ex_link_service_send_pending = 1;
3470
3471     mpt_put_msg_frame(stm_context, _IOC_ID, mf);
3472
3473     if (stm_wait_for(priv, &priv->ex_link_service_send_pending, 5, sleep) < 0)
3474         return (-1);
3475
3476     if ((be32_to_cpu(buf[0]) >> 24) != LS_ACC)
3477         return (-2);
3478
3479     *hard_address = be32_to_cpu(buf[1]);
3480
3481         TRACE_EXIT();
3482
3483     return (0);
3484 }
3485 #endif
3486 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3487 static int
3488 stm_scsi_configuration(MPT_STM_PRIV *priv,
3489                        int sleep)
3490 {
3491 #ifdef TRACING
3492     MPT_ADAPTER         *ioc = priv->ioc;
3493 #endif
3494     SCSIPortPage0_t     *ScsiPort0;
3495     SCSIPortPage1_t     *ScsiPort1;
3496     SCSIPortPage2_t     *ScsiPort2;
3497     int                 id;
3498     int                 cap;
3499     int                 wcap;
3500     int                 ncap;
3501     int                 sync;
3502     int                 flags;
3503     int                 i;
3504
3505         TRACE_ENTRY();
3506     memset(priv->hw->config_buf, 0, sizeof(priv->hw->config_buf));
3507     if (stm_get_config_page(priv, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2, 0, sleep)) {
3508         return (-1);
3509     }
3510     ScsiPort2 = &priv->SCSIPortPage2;
3511         memcpy(&priv->SCSIPortPage2, priv->hw->config_buf, sizeof(SCSIPortPage2_t));
3512
3513     id = 0;//le32_to_cpu(ScsiPort2->PortSettings) & MPI_SCSIPORTPAGE2_PORT_HOST_ID_MASK;
3514     TRACE_DBG("%s scsi id is %d", ioc->name, id);
3515     priv->port_id = id;
3516
3517     memset(priv->hw->config_buf, 0, sizeof(priv->hw->config_buf));
3518     if (stm_get_config_page(priv, MPI_CONFIG_PAGETYPE_SCSI_PORT, 0, 0, sleep)) {
3519         return (-1);
3520     }
3521         memcpy(&priv->SCSIPortPage0, priv->hw->config_buf, sizeof(SCSIPortPage0_t));
3522     ScsiPort0 = &priv->SCSIPortPage0;
3523
3524     cap = le32_to_cpu(ScsiPort0->Capabilities);
3525     TRACE_DBG("%s target %d capabilities = %08x",
3526            ioc->name, id, cap);
3527
3528     memset(priv->hw->config_buf, 0, sizeof(priv->hw->config_buf));
3529     memset(&priv->SCSIPortPage1, 0, sizeof(priv->SCSIPortPage1));
3530     ScsiPort1 = &priv->SCSIPortPage1;
3531     ScsiPort1->Configuration = cpu_to_le32(id | (1 << (id + 16)));
3532     for (i = 1; i <= priv->num_aliases; i++) {
3533         id = (priv->port_id + i) & 15;
3534         TRACE_DBG("%s alias %d is target %d",
3535                ioc->name, i, id);
3536         ScsiPort1->Configuration |= cpu_to_le32(1 << (id + 16));
3537     }
3538 //  ScsiPort1->TargetConfig = MPI_SCSIPORTPAGE1_TARGCONFIG_INIT_TARG;
3539     ScsiPort1->TargetConfig = MPI_SCSIPORTPAGE1_TARGCONFIG_TARG_ONLY;
3540 //      ScsiPort1->IDConfig = 0x7;
3541         memcpy(priv->hw->config_buf, (u32 *)ScsiPort1, sizeof(*ScsiPort1));
3542     stm_set_config_page(priv, MPI_CONFIG_PAGETYPE_SCSI_PORT, 1, 0, sleep);
3543
3544     wcap = cap & ~MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
3545     ncap = wcap & ~MPI_SCSIPORTPAGE0_CAP_WIDE;
3546
3547     memset(priv->hw->config_buf, 0, sizeof(priv->hw->config_buf));
3548     memset(priv->SCSIDevicePage1, 0, sizeof(SCSIDevicePage1_t) * NUM_SCSI_DEVICES);
3549
3550     for (i = 0; i < NUM_SCSI_DEVICES; i++) {
3551         int wide = 0;
3552     SCSIDevicePage1_t   *ScsiDevice1 = &priv->SCSIDevicePage1[i];
3553         sync = ScsiPort2->DeviceSettings[i].SyncFactor;
3554         flags = le16_to_cpu(ScsiPort2->DeviceSettings[i].DeviceFlags);
3555         if (flags & MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE)
3556             cap = ncap;
3557         else {
3558             cap = wcap;
3559                 wide = 1;
3560         }
3561         /*cap &= ~MPI_SCSIDEVPAGE1_RP_IU;
3562         cap &= ~MPI_SCSIDEVPAGE1_RP_DT;
3563         cap &= ~MPI_SCSIDEVPAGE1_RP_QAS;*/
3564         ScsiDevice1->RequestedParameters = cpu_to_le32(cap | (sync << 8));
3565         TRACE_DBG("%s initiator %d parameters = %08x, %s %s",
3566                ioc->name, i, le32_to_cpu(ScsiDevice1->RequestedParameters),
3567                    sync ? "SYNC" : " ", 
3568                    wide ? "WIDE" : " ");
3569         memcpy(priv->hw->config_buf, ScsiDevice1, sizeof(*ScsiDevice1));
3570         stm_set_config_page(priv, MPI_CONFIG_PAGETYPE_SCSI_DEVICE, 1, i, sleep);
3571     }
3572         TRACE_EXIT();
3573
3574     return (0);
3575 }
3576
3577 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3578 static int
3579 stm_sas_configuration(MPT_STM_PRIV *priv,
3580                        int sleep)
3581 {
3582     return (0);
3583 }
3584
3585 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3586 static int
3587 stm_fc_configuration(MPT_STM_PRIV *priv, int sleep)
3588 {
3589     MPT_ADAPTER         *ioc = priv->ioc;
3590     U64                 wwnn;
3591     U64                 wwpn;
3592     int                 port_id;
3593     int                 protocol;
3594     int                 flags;
3595     int                 current_speed;
3596     int                 port_state;
3597     int                 target;
3598     char                *attach;
3599     char                *speed;
3600     FCPortPage0_t       *FcPort0;
3601     FCDevicePage0_t     *FcDevice0;
3602     int                 page;
3603
3604         TRACE_ENTRY();
3605     memset(priv->hw->config_buf, 0, sizeof(priv->hw->config_buf));
3606     if (stm_get_config_page(priv, MPI_CONFIG_PAGETYPE_FC_PORT, 0, 0, sleep)) {
3607         return (-1);
3608     }
3609     FcPort0 = (FCPortPage0_t *)priv->hw->config_buf;
3610     flags = le32_to_cpu(FcPort0->Flags) &
3611         MPI_FCPORTPAGE0_FLAGS_ATTACH_TYPE_MASK;
3612     current_speed = le32_to_cpu(FcPort0->CurrentSpeed);
3613     port_state = FcPort0->PortState;
3614
3615     switch (flags) {
3616         case MPI_FCPORTPAGE0_FLAGS_ATTACH_NO_INIT:
3617             attach = NULL;
3618             break;
3619         case MPI_FCPORTPAGE0_FLAGS_ATTACH_POINT_TO_POINT:
3620             attach = "point to point";
3621             break;
3622         case MPI_FCPORTPAGE0_FLAGS_ATTACH_PRIVATE_LOOP:
3623             attach = "private loop";
3624             break;
3625         case MPI_FCPORTPAGE0_FLAGS_ATTACH_FABRIC_DIRECT:
3626             attach = "fabric direct attach";
3627             break;
3628         case MPI_FCPORTPAGE0_FLAGS_ATTACH_PUBLIC_LOOP:
3629             attach = "public loop";
3630             break;
3631         default:
3632             attach = "unknown";
3633             break;
3634     }
3635
3636     switch (current_speed) {
3637         case MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT:
3638             speed = "1 Gbaud";
3639             break;
3640         case MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT:
3641             speed = "2 Gbaud";
3642             break;
3643         case MPI_FCPORTPAGE0_CURRENT_SPEED_10GBIT:
3644             speed = "10 Gbaud";
3645             break;
3646         default:
3647             speed = "unknown";
3648             break;
3649     }
3650
3651     if (priv->port_flags != flags ||
3652         priv->port_speed != current_speed ||
3653         priv->port_state != port_state) {
3654         priv->port_flags = flags;
3655         priv->port_speed = current_speed;
3656         priv->port_state = port_state;
3657         priv->device_changed = 1;
3658         if (attach) {
3659             printk("%s link is online, type is %s, speed is %s\n",
3660                    ioc->name, attach, speed);
3661         } else {
3662             printk("%s link is offline\n", ioc->name);
3663         }
3664     }
3665
3666     wwnn.Low = le32_to_cpu(FcPort0->WWNN.Low);
3667     wwnn.High = le32_to_cpu(FcPort0->WWNN.High);
3668     wwpn.Low = le32_to_cpu(FcPort0->WWPN.Low);
3669     wwpn.High = le32_to_cpu(FcPort0->WWPN.High);
3670     port_id = le32_to_cpu(FcPort0->PortIdentifier);
3671     protocol = le32_to_cpu(FcPort0->Flags) & MPI_FCPORTPAGE0_FLAGS_PROT_MASK;
3672
3673     if (priv->wwpn.Low != wwpn.Low ||
3674         priv->wwpn.High != wwpn.High ||
3675         priv->port_id != port_id) {
3676         priv->wwnn.Low = wwnn.Low;
3677         priv->wwnn.High = wwnn.High;
3678         priv->wwpn.Low = wwpn.Low;
3679         priv->wwpn.High = wwpn.High;
3680         priv->port_id = port_id;
3681         priv->protocol = protocol;
3682         priv->device_changed = 1;
3683         if (attach) {
3684             printk("%s port is wwn %08x%08x, port id %x\n",
3685                    ioc->name, wwpn.High, wwpn.Low, port_id);
3686         } else {
3687             printk(
3688                    "%s port is wwn %08x%08x\n",
3689                    ioc->name, wwpn.High, wwpn.Low);
3690         }
3691     }
3692
3693     page = MPI_FC_DEVICE_PAGE0_PGAD_FORM_NEXT_DID + 0xffffff;
3694
3695     while (1) {
3696         memset(priv->hw->config_buf, 0, sizeof(priv->hw->config_buf));
3697         if (stm_get_config_page(priv, MPI_CONFIG_PAGETYPE_FC_DEVICE,
3698                                 0, page, sleep)) {
3699             break;
3700         }
3701         FcDevice0 = (FCDevicePage0_t *)priv->hw->config_buf;
3702
3703         wwnn.Low = le32_to_cpu(FcDevice0->WWNN.Low);
3704         wwnn.High = le32_to_cpu(FcDevice0->WWNN.High);
3705         wwpn.Low = le32_to_cpu(FcDevice0->WWPN.Low);
3706         wwpn.High = le32_to_cpu(FcDevice0->WWPN.High);
3707         port_id = le32_to_cpu(FcDevice0->PortIdentifier);
3708         protocol = FcDevice0->Protocol;
3709         if (FcDevice0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID) {
3710             target = FcDevice0->CurrentTargetID;
3711         } else {
3712             target = -1;
3713         }
3714
3715 #if 0
3716         printk("%s using ADISC to get hard address of port id %x\n",
3717                ioc->name, port_id);
3718         if (stm_get_hard_address(priv, port_id, &i, sleep))
3719             printk("%s ADISC failed!\n", ioc->name);
3720         else
3721             printk("%s port id's %x hard address is %x\n",
3722                    ioc->name, port_id, i);
3723 #endif
3724
3725         page = MPI_FC_DEVICE_PAGE0_PGAD_FORM_NEXT_DID + port_id;
3726
3727     }
3728         TRACE_EXIT();
3729
3730     return (0);
3731 }
3732
3733 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3734 static int
3735 stm_fc_enable_els(MPT_STM_PRIV *priv,
3736                   int els, int sleep)
3737 {
3738     FCPortPage8_t       *FcPort8;
3739         TRACE_ENTRY();
3740     memset(priv->hw->config_buf, 0, sizeof(priv->hw->config_buf));
3741     if (stm_get_config_page(priv, MPI_CONFIG_PAGETYPE_FC_PORT, 8, 0, sleep)) {
3742         return (-1);
3743     }
3744     FcPort8 = (FCPortPage8_t *)priv->hw->config_buf;
3745     /* clear the ELS bit */
3746     FcPort8->BitVector[els / 32] &= ~cpu_to_le32(1 << (els & 31));
3747     if (stm_set_config_page(priv, MPI_CONFIG_PAGETYPE_FC_PORT, 8, 0, sleep)) {
3748         return (-1);
3749     }
3750         TRACE_EXIT();
3751
3752     return (0);
3753 }
3754 #if 0
3755 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3756 static i