]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/ocs_fc/ocs_cam.c
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / sys / dev / ocs_fc / ocs_cam.c
1 /*-
2  * Copyright (c) 2017 Broadcom. All rights reserved.
3  * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  *    this list of conditions and the following disclaimer in the documentation
13  *    and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  * $FreeBSD$
32  */
33
34 /**
35  * @defgroup scsi_api_target SCSI Target API
36  * @defgroup scsi_api_initiator SCSI Initiator API
37  * @defgroup cam_api Common Access Method (CAM) API
38  * @defgroup cam_io CAM IO
39  */
40
41 /**
42  * @file
43  * Provides CAM functionality.
44  */
45
46 #include "ocs.h"
47 #include "ocs_scsi.h"
48 #include "ocs_device.h"
49
50 /* Default IO timeout value for initiators is 30 seconds */
51 #define OCS_CAM_IO_TIMEOUT      30
52
53 typedef struct {
54         ocs_scsi_sgl_t *sgl;
55         uint32_t sgl_max;
56         uint32_t sgl_count;
57         int32_t rc;
58 } ocs_dmamap_load_arg_t;
59
60 static void ocs_action(struct cam_sim *, union ccb *);
61 static void ocs_poll(struct cam_sim *);
62
63 static ocs_tgt_resource_t *ocs_tgt_resource_get(ocs_fcport *,
64                                         struct ccb_hdr *, uint32_t *);
65 static int32_t ocs_tgt_resource_abort(struct ocs_softc *, ocs_tgt_resource_t *);
66 static uint32_t ocs_abort_initiator_io(struct ocs_softc *ocs, union ccb *accb);
67 static void ocs_abort_inot(struct ocs_softc *ocs, union ccb *ccb);
68 static void ocs_abort_atio(struct ocs_softc *ocs, union ccb *ccb);
69 static int32_t ocs_target_tmf_cb(ocs_io_t *, ocs_scsi_io_status_e, uint32_t, void *);
70 static int32_t ocs_io_abort_cb(ocs_io_t *, ocs_scsi_io_status_e, uint32_t, void *);
71 static int32_t ocs_task_set_full_or_busy(ocs_io_t *io);
72 static int32_t ocs_initiator_tmf_cb(ocs_io_t *, ocs_scsi_io_status_e,
73                 ocs_scsi_cmd_resp_t *, uint32_t, void *);
74 static uint32_t
75 ocs_fcp_change_role(struct ocs_softc *ocs, ocs_fcport *fcp, uint32_t new_role);
76
77 static void ocs_ldt(void *arg);
78 static void ocs_ldt_task(void *arg, int pending);
79 static void ocs_delete_target(ocs_t *ocs, ocs_fcport *fcp, int tgt);
80 uint32_t ocs_add_new_tgt(ocs_node_t *node, ocs_fcport *fcp);
81 uint32_t ocs_update_tgt(ocs_node_t *node, ocs_fcport *fcp, uint32_t tgt_id);
82
83 int32_t ocs_tgt_find(ocs_fcport *fcp, ocs_node_t *node);
84
85 static inline ocs_io_t *ocs_scsi_find_io(struct ocs_softc *ocs, uint32_t tag)
86 {
87
88         return ocs_io_get_instance(ocs, tag);
89 }
90
91 static inline void ocs_target_io_free(ocs_io_t *io)
92 {
93         io->tgt_io.state = OCS_CAM_IO_FREE;
94         io->tgt_io.flags = 0;
95         io->tgt_io.app = NULL;
96         ocs_scsi_io_complete(io);
97         if(io->ocs->io_in_use != 0)
98                 atomic_subtract_acq_32(&io->ocs->io_in_use, 1);
99 }
100
101 static int32_t
102 ocs_attach_port(ocs_t *ocs, int chan)
103 {
104
105         struct cam_sim  *sim = NULL;
106         struct cam_path *path = NULL;
107         uint32_t        max_io = ocs_scsi_get_property(ocs, OCS_SCSI_MAX_IOS);
108         ocs_fcport *fcp = FCPORT(ocs, chan);
109
110         if (NULL == (sim = cam_sim_alloc(ocs_action, ocs_poll, 
111                                 device_get_name(ocs->dev), ocs, 
112                                 device_get_unit(ocs->dev), &ocs->sim_lock,
113                                 max_io, max_io, ocs->devq))) {
114                 device_printf(ocs->dev, "Can't allocate SIM\n");
115                 return 1;
116         }
117
118         mtx_lock(&ocs->sim_lock);
119         if (CAM_SUCCESS != xpt_bus_register(sim, ocs->dev, chan)) {
120                 device_printf(ocs->dev, "Can't register bus %d\n", 0);
121                 mtx_unlock(&ocs->sim_lock);
122                 cam_sim_free(sim, FALSE);
123                 return 1;
124         }
125         mtx_unlock(&ocs->sim_lock);
126
127         if (CAM_REQ_CMP != xpt_create_path(&path, NULL, cam_sim_path(sim),
128                                 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD)) {
129                 device_printf(ocs->dev, "Can't create path\n");
130                 xpt_bus_deregister(cam_sim_path(sim));
131                 mtx_unlock(&ocs->sim_lock);
132                 cam_sim_free(sim, FALSE);
133                 return 1;
134         }
135
136         fcp->ocs = ocs;
137         fcp->sim  = sim;
138         fcp->path = path;
139
140         callout_init_mtx(&fcp->ldt, &ocs->sim_lock, 0);
141         TASK_INIT(&fcp->ltask, 1, ocs_ldt_task, fcp);
142
143         return 0;
144 }
145
146 static int32_t
147 ocs_detach_port(ocs_t *ocs, int32_t chan)
148 {
149         ocs_fcport *fcp = NULL;
150         struct cam_sim  *sim = NULL;
151         struct cam_path *path = NULL;
152         fcp = FCPORT(ocs, chan);
153
154         sim = fcp->sim;
155         path = fcp->path;
156
157         callout_drain(&fcp->ldt);
158         ocs_ldt_task(fcp, 0);   
159
160         if (fcp->sim) {
161                 mtx_lock(&ocs->sim_lock);
162                         ocs_tgt_resource_abort(ocs, &fcp->targ_rsrc_wildcard);
163                         if (path) {
164                                 xpt_async(AC_LOST_DEVICE, path, NULL);
165                                 xpt_free_path(path);
166                                 fcp->path = NULL;
167                         }
168                         xpt_bus_deregister(cam_sim_path(sim));
169
170                         cam_sim_free(sim, FALSE);
171                         fcp->sim = NULL;
172                 mtx_unlock(&ocs->sim_lock);
173         }
174
175         return 0;
176 }
177
178 int32_t
179 ocs_cam_attach(ocs_t *ocs)
180 {
181         struct cam_devq *devq = NULL;
182         int     i = 0;
183         uint32_t        max_io = ocs_scsi_get_property(ocs, OCS_SCSI_MAX_IOS);
184
185         if (NULL == (devq = cam_simq_alloc(max_io))) {
186                 device_printf(ocs->dev, "Can't allocate SIMQ\n");
187                 return -1;
188         }
189
190         ocs->devq = devq;
191
192         if (mtx_initialized(&ocs->sim_lock) == 0) {
193                 mtx_init(&ocs->sim_lock, "ocs_sim_lock", NULL, MTX_DEF);
194         }
195
196         for (i = 0; i < (ocs->num_vports + 1); i++) {
197                 if (ocs_attach_port(ocs, i)) {
198                         ocs_log_err(ocs, "Attach port failed for chan: %d\n", i);
199                         goto detach_port;
200                 }
201         }
202
203         ocs->io_high_watermark = max_io;
204         ocs->io_in_use = 0;
205         return 0;
206
207 detach_port:
208         while (--i >= 0) {
209                 ocs_detach_port(ocs, i);
210         }
211
212         cam_simq_free(ocs->devq);
213
214         if (mtx_initialized(&ocs->sim_lock))
215                 mtx_destroy(&ocs->sim_lock);
216
217         return 1;       
218 }
219
220 int32_t
221 ocs_cam_detach(ocs_t *ocs)
222 {
223         int i = 0;
224
225         for (i = (ocs->num_vports); i >= 0; i--) {
226                 ocs_detach_port(ocs, i);
227         }
228
229         cam_simq_free(ocs->devq);
230
231         if (mtx_initialized(&ocs->sim_lock))
232                 mtx_destroy(&ocs->sim_lock);
233
234         return 0;
235 }
236
237 /***************************************************************************
238  * Functions required by SCSI base driver API
239  */
240
241 /**
242  * @ingroup scsi_api_target
243  * @brief Attach driver to the BSD SCSI layer (a.k.a CAM)
244  *
245  * Allocates + initializes CAM related resources and attaches to the CAM
246  *
247  * @param ocs the driver instance's software context
248  *
249  * @return 0 on success, non-zero otherwise
250  */
251 int32_t
252 ocs_scsi_tgt_new_device(ocs_t *ocs)
253 {
254         ocs->enable_task_set_full = ocs_scsi_get_property(ocs, 
255                                         OCS_SCSI_ENABLE_TASK_SET_FULL);
256         ocs_log_debug(ocs, "task set full processing is %s\n",
257                 ocs->enable_task_set_full ? "enabled" : "disabled");
258
259         return 0;
260 }
261
262 /**
263  * @ingroup scsi_api_target
264  * @brief Tears down target members of ocs structure.
265  *
266  * Called by OS code when device is removed.
267  *
268  * @param ocs pointer to ocs
269  *
270  * @return returns 0 for success, a negative error code value for failure.
271  */
272 int32_t
273 ocs_scsi_tgt_del_device(ocs_t *ocs)
274 {
275
276         return 0;
277 }
278
279 /**
280  * @ingroup scsi_api_target
281  * @brief accept new domain notification
282  *
283  * Called by base drive when new domain is discovered.  A target-server
284  * will use this call to prepare for new remote node notifications
285  * arising from ocs_scsi_new_initiator().
286  *
287  * The domain context has an element <b>ocs_scsi_tgt_domain_t tgt_domain</b> 
288  * which is declared by the target-server code and is used for target-server 
289  * private data.
290  *
291  * This function will only be called if the base-driver has been enabled for 
292  * target capability.
293  *
294  * Note that this call is made to target-server backends, 
295  * the ocs_scsi_ini_new_domain() function is called to initiator-client backends.
296  *
297  * @param domain pointer to domain
298  *
299  * @return returns 0 for success, a negative error code value for failure.
300  */
301 int32_t
302 ocs_scsi_tgt_new_domain(ocs_domain_t *domain)
303 {
304         return 0;
305 }
306
307 /**
308  * @ingroup scsi_api_target
309  * @brief accept domain lost notification
310  *
311  * Called by base-driver when a domain goes away.  A target-server will
312  * use this call to clean up all domain scoped resources.
313  *
314  * Note that this call is made to target-server backends,
315  * the ocs_scsi_ini_del_domain() function is called to initiator-client backends.
316  *
317  * @param domain pointer to domain
318  *
319  * @return returns 0 for success, a negative error code value for failure.
320  */
321 void
322 ocs_scsi_tgt_del_domain(ocs_domain_t *domain)
323 {
324 }
325
326 /**
327  * @ingroup scsi_api_target
328  * @brief accept new sli port (sport) notification
329  *
330  * Called by base drive when new sport is discovered.  A target-server
331  * will use this call to prepare for new remote node notifications
332  * arising from ocs_scsi_new_initiator().
333  *
334  * The domain context has an element <b>ocs_scsi_tgt_sport_t tgt_sport</b> 
335  * which is declared by the target-server code and is used for
336  * target-server private data.
337  *
338  * This function will only be called if the base-driver has been enabled for 
339  * target capability.
340  *
341  * Note that this call is made to target-server backends,
342  * the ocs_scsi_tgt_new_domain() is called to initiator-client backends.
343  *
344  * @param sport pointer to SLI port
345  *
346  * @return returns 0 for success, a negative error code value for failure.
347  */
348 int32_t
349 ocs_scsi_tgt_new_sport(ocs_sport_t *sport)
350 {
351         ocs_t *ocs = sport->ocs;
352
353         if(!sport->is_vport) {
354                 sport->tgt_data = FCPORT(ocs, 0);
355         }
356
357         return 0;
358 }
359
360 /**
361  * @ingroup scsi_api_target
362  * @brief accept SLI port gone notification
363  *
364  * Called by base-driver when a sport goes away.  A target-server will
365  * use this call to clean up all sport scoped resources.
366  *
367  * Note that this call is made to target-server backends,
368  * the ocs_scsi_ini_del_sport() is called to initiator-client backends.
369  *
370  * @param sport pointer to SLI port
371  *
372  * @return returns 0 for success, a negative error code value for failure.
373  */
374 void
375 ocs_scsi_tgt_del_sport(ocs_sport_t *sport)
376 {
377         return;
378 }
379
380 /**
381  * @ingroup scsi_api_target
382  * @brief receive notification of a new SCSI initiator node
383  *
384  * Sent by base driver to notify a target-server of the presense of a new
385  * remote initiator.   The target-server may use this call to prepare for
386  * inbound IO from this node.
387  *
388  * The ocs_node_t structure has and elment of type ocs_scsi_tgt_node_t named
389  * tgt_node that is declared and used by a target-server for private
390  * information.
391  *
392  * This function is only called if the target capability is enabled in driver.
393  *
394  * @param node pointer to new remote initiator node
395  *
396  * @return returns 0 for success, a negative error code value for failure.
397  *
398  * @note
399  */
400 int32_t
401 ocs_scsi_new_initiator(ocs_node_t *node)
402 {
403         ocs_t   *ocs = node->ocs;
404         struct ac_contract ac;
405         struct ac_device_changed *adc;
406
407         ocs_fcport      *fcp = NULL;
408
409         fcp = node->sport->tgt_data;
410         if (fcp == NULL) {
411                 ocs_log_err(ocs, "FCP is NULL \n");
412                 return 1;
413         }       
414
415         /*
416          * Update the IO watermark by decrementing it by the
417          * number of IOs reserved for each initiator.
418          */
419         atomic_subtract_acq_32(&ocs->io_high_watermark, OCS_RSVD_INI_IO);
420
421         ac.contract_number = AC_CONTRACT_DEV_CHG;
422         adc = (struct ac_device_changed *) ac.contract_data;
423         adc->wwpn = ocs_node_get_wwpn(node);
424         adc->port = node->rnode.fc_id;
425         adc->target = node->instance_index;
426         adc->arrived = 1;
427         xpt_async(AC_CONTRACT, fcp->path, &ac);
428
429         return 0;
430 }
431
432 /**
433  * @ingroup scsi_api_target
434  * @brief validate new initiator
435  *
436  * Sent by base driver to validate a remote initiatiator.   The target-server
437  * returns TRUE if this initiator should be accepted.
438  *
439  * This function is only called if the target capability is enabled in driver.
440  *
441  * @param node pointer to remote initiator node to validate
442  *
443  * @return TRUE if initiator should be accepted, FALSE if it should be rejected
444  *
445  * @note
446  */
447
448 int32_t
449 ocs_scsi_validate_initiator(ocs_node_t *node)
450 {
451         return 1;
452 }
453
454 /**
455  * @ingroup scsi_api_target
456  * @brief Delete a SCSI initiator node
457  *
458  * Sent by base driver to notify a target-server that a remote initiator
459  * is now gone. The base driver will have terminated all outstanding IOs 
460  * and the target-server will receive appropriate completions.
461  *
462  * This function is only called if the base driver is enabled for
463  * target capability.
464  *
465  * @param node pointer node being deleted
466  * @param reason Reason why initiator is gone.
467  *
468  * @return OCS_SCSI_CALL_COMPLETE to indicate that all work was completed
469  *
470  * @note
471  */
472 int32_t
473 ocs_scsi_del_initiator(ocs_node_t *node, ocs_scsi_del_initiator_reason_e reason)
474 {
475         ocs_t   *ocs = node->ocs;
476
477         struct ac_contract ac;
478         struct ac_device_changed *adc;
479         ocs_fcport      *fcp = NULL;
480
481         fcp = node->sport->tgt_data;
482         if (fcp == NULL) {
483                 ocs_log_err(ocs, "FCP is NULL \n");
484                 return 1;
485         }
486
487         ac.contract_number = AC_CONTRACT_DEV_CHG;
488         adc = (struct ac_device_changed *) ac.contract_data;
489         adc->wwpn = ocs_node_get_wwpn(node);
490         adc->port = node->rnode.fc_id;
491         adc->target = node->instance_index;
492         adc->arrived = 0;
493         xpt_async(AC_CONTRACT, fcp->path, &ac);
494
495         if (reason == OCS_SCSI_INITIATOR_MISSING) {
496                 return OCS_SCSI_CALL_COMPLETE;
497         }
498
499         /*
500          * Update the IO watermark by incrementing it by the
501          * number of IOs reserved for each initiator.
502          */
503         atomic_add_acq_32(&ocs->io_high_watermark, OCS_RSVD_INI_IO);
504
505         return OCS_SCSI_CALL_COMPLETE;
506 }
507
508 /**
509  * @ingroup scsi_api_target
510  * @brief receive FCP SCSI Command
511  *
512  * Called by the base driver when a new SCSI command has been received.   The
513  * target-server will process the command, and issue data and/or response phase
514  * requests to the base driver.
515  *
516  * The IO context (ocs_io_t) structure has and element of type 
517  * ocs_scsi_tgt_io_t named tgt_io that is declared and used by 
518  * a target-server for private information.
519  *
520  * @param io pointer to IO context
521  * @param lun LUN for this IO
522  * @param cdb pointer to SCSI CDB
523  * @param cdb_len length of CDB in bytes
524  * @param flags command flags
525  *
526  * @return returns 0 for success, a negative error code value for failure.
527  */
528 int32_t ocs_scsi_recv_cmd(ocs_io_t *io, uint64_t lun, uint8_t *cdb,
529                                 uint32_t cdb_len, uint32_t flags)
530 {
531         ocs_t *ocs = io->ocs;
532         struct ccb_accept_tio *atio = NULL;
533         ocs_node_t      *node = io->node;
534         ocs_tgt_resource_t *trsrc = NULL;
535         int32_t         rc = -1;
536         ocs_fcport      *fcp = NULL;
537
538         fcp = node->sport->tgt_data;
539         if (fcp == NULL) {
540                 ocs_log_err(ocs, "FCP is NULL \n");
541                 return 1;
542         }
543
544         atomic_add_acq_32(&ocs->io_in_use, 1);
545
546         /* set target io timeout */
547         io->timeout = ocs->target_io_timer_sec;
548
549         if (ocs->enable_task_set_full && 
550                 (ocs->io_in_use >= ocs->io_high_watermark)) {
551                 return ocs_task_set_full_or_busy(io);
552         } else {
553                 atomic_store_rel_32(&io->node->tgt_node.busy_sent, FALSE);
554         }
555
556         if ((lun < OCS_MAX_LUN) && fcp->targ_rsrc[lun].enabled) {
557                 trsrc = &fcp->targ_rsrc[lun];
558         } else if (fcp->targ_rsrc_wildcard.enabled) {
559                 trsrc = &fcp->targ_rsrc_wildcard;
560         }
561
562         if (trsrc) {
563                 atio = (struct ccb_accept_tio *)STAILQ_FIRST(&trsrc->atio);
564         }
565
566         if (atio) {
567                 STAILQ_REMOVE_HEAD(&trsrc->atio, sim_links.stqe);
568
569                 atio->ccb_h.status = CAM_CDB_RECVD;
570                 atio->ccb_h.target_lun = lun;
571                 atio->sense_len = 0;
572
573                 atio->init_id = node->instance_index;
574                 atio->tag_id = io->tag;
575                 atio->ccb_h.ccb_io_ptr = io;
576
577                 if (flags & OCS_SCSI_CMD_SIMPLE)
578                         atio->tag_action = MSG_SIMPLE_Q_TAG;
579                 else if (flags &  FCP_TASK_ATTR_HEAD_OF_QUEUE)
580                         atio->tag_action = MSG_HEAD_OF_Q_TAG;
581                 else if (flags & FCP_TASK_ATTR_ORDERED)
582                         atio->tag_action = MSG_ORDERED_Q_TAG;
583                 else
584                         atio->tag_action = 0;
585
586                 atio->cdb_len = cdb_len;
587                 ocs_memcpy(atio->cdb_io.cdb_bytes, cdb, cdb_len);
588
589                 io->tgt_io.flags = 0;
590                 io->tgt_io.state = OCS_CAM_IO_COMMAND;
591                 io->tgt_io.lun = lun;
592
593                 xpt_done((union ccb *)atio);
594
595                 rc = 0;
596         } else {
597                 device_printf(
598                         ocs->dev, "%s: no ATIO for LUN %lx (en=%s) OX_ID %#x\n",
599                         __func__, (unsigned long)lun,
600                         trsrc ? (trsrc->enabled ? "T" : "F") : "X",
601                         be16toh(io->init_task_tag));
602
603                 io->tgt_io.state = OCS_CAM_IO_MAX;
604                 ocs_target_io_free(io);
605         }
606
607         return rc;
608 }
609
610 /**
611  * @ingroup scsi_api_target
612  * @brief receive FCP SCSI Command with first burst data.
613  *
614  * Receive a new FCP SCSI command from the base driver with first burst data.
615  *
616  * @param io pointer to IO context
617  * @param lun LUN for this IO
618  * @param cdb pointer to SCSI CDB
619  * @param cdb_len length of CDB in bytes
620  * @param flags command flags
621  * @param first_burst_buffers first burst buffers
622  * @param first_burst_buffer_count The number of bytes received in the first burst
623  *
624  * @return returns 0 for success, a negative error code value for failure.
625  */
626 int32_t ocs_scsi_recv_cmd_first_burst(ocs_io_t *io, uint64_t lun, uint8_t *cdb,
627                                         uint32_t cdb_len, uint32_t flags, 
628                                         ocs_dma_t first_burst_buffers[], 
629                                         uint32_t first_burst_buffer_count)
630 {
631         return -1;
632 }
633
634 /**
635  * @ingroup scsi_api_target
636  * @brief receive a TMF command IO
637  *
638  * Called by the base driver when a SCSI TMF command has been received.   The
639  * target-server will process the command, aborting commands as needed, and post
640  * a response using ocs_scsi_send_resp()
641  *
642  * The IO context (ocs_io_t) structure has and element of type ocs_scsi_tgt_io_t named
643  * tgt_io that is declared and used by a target-server for private information.
644  *
645  * If the target-server walks the nodes active_ios linked list, and starts IO
646  * abort processing, the code <b>must</b> be sure not to abort the IO passed into the
647  * ocs_scsi_recv_tmf() command.
648  *
649  * @param tmfio pointer to IO context
650  * @param lun logical unit value
651  * @param cmd command request
652  * @param abortio pointer to IO object to abort for TASK_ABORT (NULL for all other TMF)
653  * @param flags flags
654  *
655  * @return returns 0 for success, a negative error code value for failure.
656  */
657 int32_t ocs_scsi_recv_tmf(ocs_io_t *tmfio, uint64_t lun, ocs_scsi_tmf_cmd_e cmd,
658                                 ocs_io_t *abortio, uint32_t flags)
659 {
660         ocs_t *ocs = tmfio->ocs;
661         ocs_node_t *node = tmfio->node;
662         ocs_tgt_resource_t *trsrc = NULL;
663         struct ccb_immediate_notify *inot = NULL;
664         int32_t         rc = -1;
665         ocs_fcport      *fcp = NULL;
666
667         fcp = node->sport->tgt_data;
668         if (fcp == NULL) {
669                 ocs_log_err(ocs, "FCP is NULL \n");
670                 return 1;
671         }
672
673         if ((lun < OCS_MAX_LUN) && fcp->targ_rsrc[lun].enabled) {
674                 trsrc = &fcp->targ_rsrc[lun];
675         } else if (fcp->targ_rsrc_wildcard.enabled) {
676                 trsrc = &fcp->targ_rsrc_wildcard;
677         }
678
679         device_printf(tmfio->ocs->dev, "%s: io=%p cmd=%#x LU=%lx en=%s\n",
680                         __func__, tmfio, cmd, (unsigned long)lun,
681                         trsrc ? (trsrc->enabled ? "T" : "F") : "X");
682         if (trsrc) {
683                 inot = (struct ccb_immediate_notify *)STAILQ_FIRST(&trsrc->inot);
684         }
685
686         if (!inot) {
687                 device_printf(
688                         ocs->dev, "%s: no INOT for LUN %llx (en=%s) OX_ID %#x\n",
689                         __func__, (unsigned long long)lun, trsrc ? (trsrc->enabled ? "T" : "F") : "X",
690                         be16toh(tmfio->init_task_tag));
691
692                 if (abortio) {
693                         ocs_scsi_io_complete(abortio);
694                 }
695                 ocs_scsi_io_complete(tmfio);
696                 goto ocs_scsi_recv_tmf_out;
697         }
698
699         tmfio->tgt_io.app = abortio;
700
701         STAILQ_REMOVE_HEAD(&trsrc->inot, sim_links.stqe);
702
703         inot->tag_id = tmfio->tag;
704         inot->seq_id = tmfio->tag;
705
706         if ((lun < OCS_MAX_LUN) && fcp->targ_rsrc[lun].enabled) {
707                 inot->initiator_id = node->instance_index;
708         } else {
709                 inot->initiator_id = CAM_TARGET_WILDCARD;
710         } 
711
712         inot->ccb_h.status = CAM_MESSAGE_RECV;
713         inot->ccb_h.target_lun = lun;
714
715         switch (cmd) {
716         case OCS_SCSI_TMF_ABORT_TASK:
717                 inot->arg = MSG_ABORT_TASK;
718                 inot->seq_id = abortio->tag;
719                 device_printf(ocs->dev, "%s: ABTS IO.%#x st=%#x\n", 
720                         __func__, abortio->tag, abortio->tgt_io.state);
721                 abortio->tgt_io.flags |= OCS_CAM_IO_F_ABORT_RECV;
722                 abortio->tgt_io.flags |= OCS_CAM_IO_F_ABORT_NOTIFY;
723                 break;
724         case OCS_SCSI_TMF_QUERY_TASK_SET:
725                 device_printf(ocs->dev, 
726                         "%s: OCS_SCSI_TMF_QUERY_TASK_SET not supported\n",
727                                 __func__);
728                 STAILQ_INSERT_TAIL(&trsrc->inot, &inot->ccb_h, sim_links.stqe);
729                 ocs_scsi_io_complete(tmfio);
730                 goto ocs_scsi_recv_tmf_out;
731                 break;
732         case OCS_SCSI_TMF_ABORT_TASK_SET:
733                 inot->arg = MSG_ABORT_TASK_SET;
734                 break;
735         case OCS_SCSI_TMF_CLEAR_TASK_SET:
736                 inot->arg = MSG_CLEAR_TASK_SET;
737                 break;
738         case OCS_SCSI_TMF_QUERY_ASYNCHRONOUS_EVENT:
739                 inot->arg = MSG_QUERY_ASYNC_EVENT;
740                 break;
741         case OCS_SCSI_TMF_LOGICAL_UNIT_RESET:
742                 inot->arg = MSG_LOGICAL_UNIT_RESET;
743                 break;
744         case OCS_SCSI_TMF_CLEAR_ACA:
745                 inot->arg = MSG_CLEAR_ACA;
746                 break;
747         case OCS_SCSI_TMF_TARGET_RESET:
748                 inot->arg = MSG_TARGET_RESET;
749                 break;
750         default:
751                 device_printf(ocs->dev, "%s: unsupported TMF %#x\n",
752                                                          __func__, cmd);
753                 STAILQ_INSERT_TAIL(&trsrc->inot, &inot->ccb_h, sim_links.stqe);
754                 goto ocs_scsi_recv_tmf_out;
755         }
756
757         rc = 0;
758
759         xpt_print(inot->ccb_h.path, "%s: func=%#x stat=%#x id=%#x lun=%#x"
760                         " flags=%#x tag=%#x seq=%#x ini=%#x arg=%#x\n", 
761                         __func__, inot->ccb_h.func_code, inot->ccb_h.status,
762                         inot->ccb_h.target_id, 
763                         (unsigned int)inot->ccb_h.target_lun, inot->ccb_h.flags,
764                         inot->tag_id, inot->seq_id, inot->initiator_id,
765                         inot->arg);
766         xpt_done((union ccb *)inot);
767
768         if (abortio) {
769                 abortio->tgt_io.flags |= OCS_CAM_IO_F_ABORT_DEV;
770                 rc = ocs_scsi_tgt_abort_io(abortio, ocs_io_abort_cb, tmfio);
771         }
772
773 ocs_scsi_recv_tmf_out:
774         return rc;
775 }
776
777 /**
778  * @ingroup scsi_api_initiator
779  * @brief Initializes any initiator fields on the ocs structure.
780  *
781  * Called by OS initialization code when a new device is discovered.
782  *
783  * @param ocs pointer to ocs
784  *
785  * @return returns 0 for success, a negative error code value for failure.
786  */
787 int32_t
788 ocs_scsi_ini_new_device(ocs_t *ocs)
789 {
790
791         return 0;
792 }
793
794 /**
795  * @ingroup scsi_api_initiator
796  * @brief Tears down initiator members of ocs structure.
797  *
798  * Called by OS code when device is removed.
799  *
800  * @param ocs pointer to ocs
801  *
802  * @return returns 0 for success, a negative error code value for failure.
803  */
804
805 int32_t
806 ocs_scsi_ini_del_device(ocs_t *ocs)
807 {
808
809         return 0;
810 }
811
812 /**
813  * @ingroup scsi_api_initiator
814  * @brief accept new domain notification
815  *
816  * Called by base drive when new domain is discovered.  An initiator-client
817  * will accept this call to prepare for new remote node notifications
818  * arising from ocs_scsi_new_target().
819  *
820  * The domain context has the element <b>ocs_scsi_ini_domain_t ini_domain</b>
821  * which is declared by the initiator-client code and is used for 
822  * initiator-client private data.
823  *
824  * This function will only be called if the base-driver has been enabled for 
825  * initiator capability.
826  *
827  * Note that this call is made to initiator-client backends, 
828  * the ocs_scsi_tgt_new_domain() function is called to target-server backends.
829  *
830  * @param domain pointer to domain
831  *
832  * @return returns 0 for success, a negative error code value for failure.
833  */
834 int32_t
835 ocs_scsi_ini_new_domain(ocs_domain_t *domain)
836 {
837         return 0;
838 }
839
840 /**
841  * @ingroup scsi_api_initiator
842  * @brief accept domain lost notification
843  *
844  * Called by base-driver when a domain goes away.  An initiator-client will
845  * use this call to clean up all domain scoped resources.
846  *
847  * This function will only be called if the base-driver has been enabled for
848  * initiator capability.
849  *
850  * Note that this call is made to initiator-client backends,
851  * the ocs_scsi_tgt_del_domain() function is called to target-server backends.
852  *
853  * @param domain pointer to domain
854  *
855  * @return returns 0 for success, a negative error code value for failure.
856  */
857 void
858 ocs_scsi_ini_del_domain(ocs_domain_t *domain)
859 {
860 }
861
862 /**
863  * @ingroup scsi_api_initiator
864  * @brief accept new sli port notification
865  *
866  * Called by base drive when new sli port (sport) is discovered.
867  * A target-server will use this call to prepare for new remote node
868  * notifications arising from ocs_scsi_new_initiator().
869  *
870  * This function will only be called if the base-driver has been enabled for
871  * target capability.
872  *
873  * Note that this call is made to target-server backends,
874  * the ocs_scsi_ini_new_sport() function is called to initiator-client backends.
875  *
876  * @param sport pointer to sport
877  *
878  * @return returns 0 for success, a negative error code value for failure.
879  */
880 int32_t
881 ocs_scsi_ini_new_sport(ocs_sport_t *sport)
882 {
883         ocs_t *ocs = sport->ocs;
884         ocs_fcport *fcp = FCPORT(ocs, 0);
885
886         if (!sport->is_vport) {
887                 sport->tgt_data = fcp;
888                 fcp->fc_id = sport->fc_id;      
889         }
890
891         return 0;
892 }
893
894 /**
895  * @ingroup scsi_api_initiator
896  * @brief accept sli port gone notification
897  *
898  * Called by base-driver when a sport goes away.  A target-server will
899  * use this call to clean up all sport scoped resources.
900  *
901  * Note that this call is made to target-server backends,
902  * the ocs_scsi_ini_del_sport() function is called to initiator-client backends.
903  *
904  * @param sport pointer to SLI port
905  *
906  * @return returns 0 for success, a negative error code value for failure.
907  */
908 void
909 ocs_scsi_ini_del_sport(ocs_sport_t *sport)
910 {
911         ocs_t *ocs = sport->ocs;
912         ocs_fcport *fcp = FCPORT(ocs, 0);
913
914         if (!sport->is_vport) {
915                 fcp->fc_id = 0; 
916         }
917 }
918
919 void 
920 ocs_scsi_sport_deleted(ocs_sport_t *sport)
921 {
922         ocs_t *ocs = sport->ocs;
923         ocs_fcport *fcp = NULL;
924
925         ocs_xport_stats_t value;
926
927         if (!sport->is_vport) {
928                 return;
929         }
930
931         fcp = sport->tgt_data;
932
933         ocs_xport_status(ocs->xport, OCS_XPORT_PORT_STATUS, &value);
934
935         if (value.value == 0) {
936                 ocs_log_debug(ocs, "PORT offline,.. skipping\n");
937                 return;
938         }       
939
940         if ((fcp->role != KNOB_ROLE_NONE)) {
941                 if(fcp->vport->sport != NULL) {
942                         ocs_log_debug(ocs,"sport is not NULL, skipping\n");
943                         return;
944                 }
945
946                 ocs_sport_vport_alloc(ocs->domain, fcp->vport);
947                 return;
948         }
949
950 }
951
952 int32_t
953 ocs_tgt_find(ocs_fcport *fcp, ocs_node_t *node)
954 {
955         ocs_fc_target_t *tgt = NULL;
956         uint32_t i;
957
958         for (i = 0; i < OCS_MAX_TARGETS; i++) {
959                 tgt = &fcp->tgt[i];
960
961                 if (tgt->state == OCS_TGT_STATE_NONE)
962                         continue;
963                 
964                 if (ocs_node_get_wwpn(node) == tgt->wwpn) {
965                         return i;
966                 }
967         }
968
969         return -1;
970 }
971
972 /**
973  * @ingroup scsi_api_initiator
974  * @brief receive notification of a new SCSI target node
975  *
976  * Sent by base driver to notify an initiator-client of the presense of a new
977  * remote target.   The initiator-server may use this call to prepare for
978  * inbound IO from this node.
979  *
980  * This function is only called if the base driver is enabled for
981  * initiator capability.
982  *
983  * @param node pointer to new remote initiator node
984  *
985  * @return none
986  *
987  * @note
988  */
989
990 uint32_t
991 ocs_update_tgt(ocs_node_t *node, ocs_fcport *fcp, uint32_t tgt_id)
992 {
993         ocs_fc_target_t *tgt = NULL;
994
995         tgt = &fcp->tgt[tgt_id];
996
997         tgt->node_id = node->instance_index;
998         tgt->state = OCS_TGT_STATE_VALID;
999
1000         tgt->port_id = node->rnode.fc_id;
1001         tgt->wwpn = ocs_node_get_wwpn(node);
1002         tgt->wwnn = ocs_node_get_wwnn(node);
1003         return 0;
1004 }
1005
1006 uint32_t
1007 ocs_add_new_tgt(ocs_node_t *node, ocs_fcport *fcp)
1008 {
1009         uint32_t i;
1010
1011         struct ocs_softc *ocs = node->ocs;
1012         union ccb *ccb = NULL;
1013         for (i = 0; i < OCS_MAX_TARGETS; i++) {
1014                 if (fcp->tgt[i].state == OCS_TGT_STATE_NONE)
1015                         break;
1016         }
1017
1018         if (NULL == (ccb = xpt_alloc_ccb_nowait())) {
1019                 device_printf(ocs->dev, "%s: ccb allocation failed\n", __func__);
1020                 return -1;
1021         }
1022
1023         if (CAM_REQ_CMP != xpt_create_path(&ccb->ccb_h.path, xpt_periph,
1024                                 cam_sim_path(fcp->sim),
1025                                 i, CAM_LUN_WILDCARD)) {
1026                 device_printf(
1027                         ocs->dev, "%s: target path creation failed\n", __func__);
1028                 xpt_free_ccb(ccb);
1029                 return -1;
1030         }
1031
1032         ocs_update_tgt(node, fcp, i);
1033         xpt_rescan(ccb);
1034         return 0;
1035 }
1036
1037 int32_t
1038 ocs_scsi_new_target(ocs_node_t *node)
1039 {
1040         ocs_fcport      *fcp = NULL;
1041         int32_t i;
1042
1043         fcp = node->sport->tgt_data;
1044         if (fcp == NULL) {
1045                 printf("%s:FCP is NULL \n", __func__);
1046                 return 0;
1047         }
1048
1049         i = ocs_tgt_find(fcp, node);
1050
1051         if (i < 0) {
1052                 ocs_add_new_tgt(node, fcp);
1053                 return 0;
1054         }
1055
1056         ocs_update_tgt(node, fcp, i);
1057         return 0;
1058 }
1059
1060 static void
1061 ocs_delete_target(ocs_t *ocs, ocs_fcport *fcp, int tgt)
1062 {
1063         struct cam_path *cpath = NULL;
1064
1065         if (!fcp->sim) { 
1066                 device_printf(ocs->dev, "%s: calling with NULL sim\n", __func__); 
1067                 return;
1068         }
1069
1070         if (CAM_REQ_CMP == xpt_create_path(&cpath, NULL, cam_sim_path(fcp->sim),
1071                                 tgt, CAM_LUN_WILDCARD)) {
1072                 xpt_async(AC_LOST_DEVICE, cpath, NULL);
1073                 
1074                 xpt_free_path(cpath);
1075         }
1076 }
1077
1078 /*
1079  * Device Lost Timer Function- when we have decided that a device was lost,
1080  * we wait a specific period of time prior to telling the OS about lost device.
1081  *
1082  * This timer function gets activated when the device was lost. 
1083  * This function fires once a second and then scans the port database
1084  * for devices that are marked dead but still have a virtual target assigned.
1085  * We decrement a counter for that port database entry, and when it hits zero,
1086  * we tell the OS the device was lost. Timer will be stopped when the device
1087  * comes back active or removed from the OS.
1088  */
1089 static void
1090 ocs_ldt(void *arg)
1091 {
1092         ocs_fcport *fcp = arg;
1093         taskqueue_enqueue(taskqueue_thread, &fcp->ltask);
1094 }
1095
1096 static void
1097 ocs_ldt_task(void *arg, int pending)
1098 {
1099         ocs_fcport *fcp = arg;
1100         ocs_t   *ocs = fcp->ocs;
1101         int i, more_to_do = 0;
1102         ocs_fc_target_t *tgt = NULL;
1103
1104         for (i = 0; i < OCS_MAX_TARGETS; i++) {
1105                 tgt = &fcp->tgt[i];
1106
1107                 if (tgt->state != OCS_TGT_STATE_LOST) {
1108                         continue;
1109                 }
1110
1111                 if ((tgt->gone_timer != 0) && (ocs->attached)){
1112                         tgt->gone_timer -= 1;
1113                         more_to_do++;
1114                         continue;
1115                 }
1116
1117                 if (tgt->is_target) {
1118                         tgt->is_target = 0;
1119                         ocs_delete_target(ocs, fcp, i);
1120                 }
1121
1122                 tgt->state = OCS_TGT_STATE_NONE;
1123         }
1124
1125         if (more_to_do) {
1126                 callout_reset(&fcp->ldt, hz, ocs_ldt, fcp);
1127         } else {
1128                 callout_deactivate(&fcp->ldt);
1129         }
1130
1131 }
1132
1133 /**
1134  * @ingroup scsi_api_initiator
1135  * @brief Delete a SCSI target node
1136  *
1137  * Sent by base driver to notify a initiator-client that a remote target 
1138  * is now gone. The base driver will have terminated all  outstanding IOs 
1139  * and the initiator-client will receive appropriate completions.
1140  *
1141  * The ocs_node_t structure has and elment of type ocs_scsi_ini_node_t named
1142  * ini_node that is declared and used by a target-server for private
1143  * information.
1144  *
1145  * This function is only called if the base driver is enabled for
1146  * initiator capability.
1147  *
1148  * @param node pointer node being deleted
1149  * @param reason reason for deleting the target
1150  *
1151  * @return Returns OCS_SCSI_CALL_ASYNC if target delete is queued for async 
1152  * completion and OCS_SCSI_CALL_COMPLETE if call completed or error.
1153  *
1154  * @note
1155  */
1156 int32_t
1157 ocs_scsi_del_target(ocs_node_t *node, ocs_scsi_del_target_reason_e reason)
1158 {
1159         struct ocs_softc *ocs = node->ocs;
1160         ocs_fcport      *fcp = NULL;
1161         ocs_fc_target_t *tgt = NULL;
1162         int32_t tgt_id;
1163
1164         if (ocs == NULL) {
1165                 ocs_log_err(ocs,"OCS is NULL \n");
1166                 return -1;
1167         }
1168
1169         fcp = node->sport->tgt_data;
1170         if (fcp == NULL) {
1171                 ocs_log_err(ocs,"FCP is NULL \n");
1172                 return -1;
1173         }
1174
1175         tgt_id = ocs_tgt_find(fcp, node);
1176         if (tgt_id == -1) {
1177                 ocs_log_err(ocs,"target is invalid\n");
1178                 return -1;
1179         }
1180
1181         tgt = &fcp->tgt[tgt_id];
1182
1183         // IF in shutdown delete target.
1184         if(!ocs->attached) {
1185                 ocs_delete_target(ocs, fcp, tgt_id);
1186         } else {
1187                 tgt->state = OCS_TGT_STATE_LOST;
1188                 tgt->gone_timer = 30;
1189                 if (!callout_active(&fcp->ldt)) {
1190                         callout_reset(&fcp->ldt, hz, ocs_ldt, fcp);
1191                 }
1192         }
1193
1194         return 0;
1195 }
1196
1197 /**
1198  * @brief Initialize SCSI IO
1199  *
1200  * Initialize SCSI IO, this function is called once per IO during IO pool
1201  * allocation so that the target server may initialize any of its own private
1202  * data.
1203  *
1204  * @param io pointer to SCSI IO object
1205  *
1206  * @return returns 0 for success, a negative error code value for failure.
1207  */
1208 int32_t
1209 ocs_scsi_tgt_io_init(ocs_io_t *io)
1210 {
1211         return 0;
1212 }
1213
1214 /**
1215  * @brief Uninitialize SCSI IO
1216  *
1217  * Uninitialize target server private data in a SCSI io object
1218  *
1219  * @param io pointer to SCSI IO object
1220  *
1221  * @return returns 0 for success, a negative error code value for failure.
1222  */
1223 int32_t
1224 ocs_scsi_tgt_io_exit(ocs_io_t *io)
1225 {
1226         return 0;
1227 }
1228
1229 /**
1230  * @brief Initialize SCSI IO
1231  *
1232  * Initialize SCSI IO, this function is called once per IO during IO pool
1233  * allocation so that the initiator client may initialize any of its own private
1234  * data.
1235  *
1236  * @param io pointer to SCSI IO object
1237  *
1238  * @return returns 0 for success, a negative error code value for failure.
1239  */
1240 int32_t
1241 ocs_scsi_ini_io_init(ocs_io_t *io)
1242 {
1243         return 0;
1244 }
1245
1246 /**
1247  * @brief Uninitialize SCSI IO
1248  *
1249  * Uninitialize initiator client private data in a SCSI io object
1250  *
1251  * @param io pointer to SCSI IO object
1252  *
1253  * @return returns 0 for success, a negative error code value for failure.
1254  */
1255 int32_t
1256 ocs_scsi_ini_io_exit(ocs_io_t *io)
1257 {
1258         return 0;
1259 }
1260 /*
1261  * End of functions required by SCSI base driver API
1262  ***************************************************************************/
1263
1264 static __inline void
1265 ocs_set_ccb_status(union ccb *ccb, cam_status status)
1266 {
1267         ccb->ccb_h.status &= ~CAM_STATUS_MASK;
1268         ccb->ccb_h.status |= status;
1269 }
1270
1271 static int32_t
1272 ocs_task_set_full_or_busy_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status,
1273                                                 uint32_t flags, void *arg)
1274 {
1275
1276         ocs_target_io_free(io);
1277
1278         return 0;
1279 }
1280
1281 /**
1282  * @brief send SCSI task set full or busy status
1283  *
1284  * A SCSI task set full or busy response is sent depending on whether
1285  * another IO is already active on the LUN.
1286  *
1287  * @param io pointer to IO context
1288  *
1289  * @return returns 0 for success, a negative error code value for failure.
1290  */
1291
1292 static int32_t
1293 ocs_task_set_full_or_busy(ocs_io_t *io)
1294 {
1295         ocs_scsi_cmd_resp_t rsp = { 0 };
1296         ocs_t *ocs = io->ocs;
1297
1298         /*
1299          * If there is another command for the LUN, then send task set full,
1300          * if this is the first one, then send the busy status.
1301          *
1302          * if 'busy sent' is FALSE, set it to TRUE and send BUSY
1303          * otherwise send FULL
1304          */
1305         if (atomic_cmpset_acq_32(&io->node->tgt_node.busy_sent, FALSE, TRUE)) {
1306                 rsp.scsi_status = SCSI_STATUS_BUSY; /* Busy */
1307                 printf("%s: busy [%s] tag=%x iiu=%d ihw=%d\n", __func__,
1308                                 io->node->display_name, io->tag,
1309                                 io->ocs->io_in_use, io->ocs->io_high_watermark);
1310         } else {
1311                 rsp.scsi_status = SCSI_STATUS_TASK_SET_FULL; /* Task set full */
1312                 printf("%s: full tag=%x iiu=%d\n", __func__, io->tag,
1313                         io->ocs->io_in_use);
1314         }
1315
1316         /* Log a message here indicating a busy or task set full state */
1317         if (OCS_LOG_ENABLE_Q_FULL_BUSY_MSG(ocs)) {
1318                 /* Log Task Set Full */
1319                 if (rsp.scsi_status == SCSI_STATUS_TASK_SET_FULL) {
1320                         /* Task Set Full Message */
1321                         ocs_log_info(ocs, "OCS CAM TASK SET FULL. Tasks >= %d\n",
1322                                         ocs->io_high_watermark);
1323                 }
1324                 else if (rsp.scsi_status == SCSI_STATUS_BUSY) {
1325                         /* Log Busy Message */
1326                         ocs_log_info(ocs, "OCS CAM SCSI BUSY\n");
1327                 }
1328         }
1329
1330         /* Send the response */
1331         return 
1332         ocs_scsi_send_resp(io, 0, &rsp, ocs_task_set_full_or_busy_cb, NULL);
1333 }
1334
1335 /**
1336  * @ingroup cam_io
1337  * @brief Process target IO completions
1338  *
1339  * @param io 
1340  * @param scsi_status did the IO complete successfully
1341  * @param flags 
1342  * @param arg application specific pointer provided in the call to ocs_target_io()
1343  *
1344  * @todo
1345  */
1346 static int32_t ocs_scsi_target_io_cb(ocs_io_t *io, 
1347                                 ocs_scsi_io_status_e scsi_status,
1348                                 uint32_t flags, void *arg)
1349 {
1350         union ccb *ccb = arg;
1351         struct ccb_scsiio *csio = &ccb->csio;
1352         struct ocs_softc *ocs = csio->ccb_h.ccb_ocs_ptr;
1353         uint32_t cam_dir = ccb->ccb_h.flags & CAM_DIR_MASK;
1354         uint32_t io_is_done = 
1355                 (ccb->ccb_h.flags & CAM_SEND_STATUS) == CAM_SEND_STATUS;
1356
1357         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1358
1359         if (CAM_DIR_NONE != cam_dir) {
1360                 bus_dmasync_op_t op;
1361
1362                 if (CAM_DIR_IN == cam_dir) {
1363                         op = BUS_DMASYNC_POSTREAD;
1364                 } else {
1365                         op = BUS_DMASYNC_POSTWRITE;
1366                 }
1367                 /* Synchronize the DMA memory with the CPU and free the mapping */
1368                 bus_dmamap_sync(ocs->buf_dmat, io->tgt_io.dmap, op);
1369                 if (io->tgt_io.flags & OCS_CAM_IO_F_DMAPPED) {
1370                         bus_dmamap_unload(ocs->buf_dmat, io->tgt_io.dmap);
1371                 }
1372         }
1373
1374         if (io->tgt_io.sendresp) {
1375                 io->tgt_io.sendresp = 0;
1376                 ocs_scsi_cmd_resp_t  resp = { 0 };
1377                 io->tgt_io.state = OCS_CAM_IO_RESP;
1378                 resp.scsi_status = scsi_status;
1379                 if (ccb->ccb_h.flags & CAM_SEND_SENSE) {
1380                         resp.sense_data = (uint8_t *)&csio->sense_data;
1381                         resp.sense_data_length = csio->sense_len;
1382                 }
1383                 resp.residual = io->exp_xfer_len - io->transferred;
1384
1385                 return ocs_scsi_send_resp(io, 0, &resp, ocs_scsi_target_io_cb, ccb);
1386         }
1387
1388         switch (scsi_status) {
1389         case OCS_SCSI_STATUS_GOOD:
1390                 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
1391                 break;
1392         case OCS_SCSI_STATUS_ABORTED:
1393                 ocs_set_ccb_status(ccb, CAM_REQ_ABORTED);
1394                 break;
1395         default:
1396                 ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
1397         }
1398
1399         if (io_is_done) {
1400                 if ((io->tgt_io.flags & OCS_CAM_IO_F_ABORT_NOTIFY) == 0) {
1401                         ocs_target_io_free(io);
1402                 }
1403         } else {
1404                 io->tgt_io.state = OCS_CAM_IO_DATA_DONE;
1405                 /*device_printf(ocs->dev, "%s: CTIO state=%d tag=%#x\n",
1406                                 __func__, io->tgt_io.state, io->tag);*/
1407         }
1408
1409         xpt_done(ccb);
1410
1411         return 0;
1412 }
1413
1414 /**
1415  * @note        1. Since the CCB is assigned to the ocs_io_t on an XPT_CONT_TARGET_IO
1416  *                 action, if an initiator aborts a command prior to the SIM receiving
1417  *                 a CTIO, the IO's CCB will be NULL.
1418  */
1419 static int32_t
1420 ocs_io_abort_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status, uint32_t flags, void *arg)
1421 {
1422         struct ocs_softc *ocs = NULL;
1423         ocs_io_t        *tmfio = arg;
1424         ocs_scsi_tmf_resp_e tmf_resp = OCS_SCSI_TMF_FUNCTION_COMPLETE;
1425         int32_t rc = 0;
1426
1427         ocs = io->ocs;
1428
1429         io->tgt_io.flags &= ~OCS_CAM_IO_F_ABORT_DEV;
1430
1431         /* A good status indicates the IO was aborted and will be completed in
1432          * the IO's completion handler. Handle the other cases here. */
1433         switch (scsi_status) {
1434         case OCS_SCSI_STATUS_GOOD:
1435                 break;
1436         case OCS_SCSI_STATUS_NO_IO:
1437                 break;
1438         default:
1439                 device_printf(ocs->dev, "%s: unhandled status %d\n",
1440                                 __func__, scsi_status);
1441                 tmf_resp = OCS_SCSI_TMF_FUNCTION_REJECTED;
1442                 rc = -1;
1443         }
1444
1445         ocs_scsi_send_tmf_resp(tmfio, tmf_resp, NULL, ocs_target_tmf_cb, NULL);
1446
1447         return rc;
1448 }
1449
1450 /**
1451  * @ingroup cam_io
1452  * @brief Process initiator IO completions
1453  *
1454  * @param io 
1455  * @param scsi_status did the IO complete successfully
1456  * @param rsp pointer to response buffer
1457  * @param flags 
1458  * @param arg application specific pointer provided in the call to ocs_target_io()
1459  *
1460  * @todo
1461  */
1462 static int32_t ocs_scsi_initiator_io_cb(ocs_io_t *io,
1463                                         ocs_scsi_io_status_e scsi_status,
1464                                         ocs_scsi_cmd_resp_t *rsp,
1465                                         uint32_t flags, void *arg)
1466 {
1467         union ccb *ccb = arg;
1468         struct ccb_scsiio *csio = &ccb->csio;
1469         struct ocs_softc *ocs = csio->ccb_h.ccb_ocs_ptr;
1470         uint32_t cam_dir = ccb->ccb_h.flags & CAM_DIR_MASK;
1471         cam_status ccb_status= CAM_REQ_CMP_ERR;
1472
1473         if (CAM_DIR_NONE != cam_dir) {
1474                 bus_dmasync_op_t op;
1475
1476                 if (CAM_DIR_IN == cam_dir) {
1477                         op = BUS_DMASYNC_POSTREAD;
1478                 } else {
1479                         op = BUS_DMASYNC_POSTWRITE;
1480                 }
1481                 /* Synchronize the DMA memory with the CPU and free the mapping */
1482                 bus_dmamap_sync(ocs->buf_dmat, io->tgt_io.dmap, op);
1483                 if (io->tgt_io.flags & OCS_CAM_IO_F_DMAPPED) {
1484                         bus_dmamap_unload(ocs->buf_dmat, io->tgt_io.dmap);
1485                 }
1486         }
1487
1488         if (scsi_status == OCS_SCSI_STATUS_CHECK_RESPONSE) {
1489                 csio->scsi_status = rsp->scsi_status;
1490                 if (SCSI_STATUS_OK != rsp->scsi_status) {
1491                         ccb_status = CAM_SCSI_STATUS_ERROR;
1492                 }
1493
1494                 csio->resid = rsp->residual;
1495                 if (rsp->residual > 0) {
1496                         uint32_t length = rsp->response_wire_length;
1497                         /* underflow */
1498                         if (csio->dxfer_len == (length + csio->resid)) {
1499                                 ccb_status = CAM_REQ_CMP;
1500                         }
1501                 } else if (rsp->residual < 0) {
1502                         ccb_status = CAM_DATA_RUN_ERR;
1503                 }
1504
1505                 if ((rsp->sense_data_length) &&
1506                         !(ccb->ccb_h.flags & (CAM_SENSE_PHYS | CAM_SENSE_PTR))) {
1507                         uint32_t        sense_len = 0;
1508
1509                         ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
1510                         if (rsp->sense_data_length < csio->sense_len) {
1511                                 csio->sense_resid = 
1512                                         csio->sense_len - rsp->sense_data_length;
1513                                 sense_len = rsp->sense_data_length;
1514                         } else {
1515                                 csio->sense_resid = 0;
1516                                 sense_len = csio->sense_len;
1517                         }
1518                         ocs_memcpy(&csio->sense_data, rsp->sense_data, sense_len);
1519                 }
1520         } else if (scsi_status != OCS_SCSI_STATUS_GOOD) {
1521                 ccb_status = CAM_REQ_CMP_ERR;
1522                 ocs_set_ccb_status(ccb, ccb_status);
1523                 csio->ccb_h.status |= CAM_DEV_QFRZN;
1524                 xpt_freeze_devq(csio->ccb_h.path, 1);
1525
1526         } else {
1527                 ccb_status = CAM_REQ_CMP;
1528         }
1529
1530         ocs_set_ccb_status(ccb, ccb_status);
1531
1532         ocs_scsi_io_free(io);
1533
1534         csio->ccb_h.ccb_io_ptr = NULL;
1535         csio->ccb_h.ccb_ocs_ptr = NULL;
1536         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1537
1538         xpt_done(ccb);
1539
1540         return 0;
1541 }
1542
1543 /**
1544  * @brief Load scatter-gather list entries into an IO
1545  *
1546  * This routine relies on the driver instance's software context pointer and
1547  * the IO object pointer having been already assigned to hooks in the CCB.
1548  * Although the routine does not return success/fail, callers can look at the
1549  * n_sge member to determine if the mapping failed (0 on failure).
1550  *
1551  * @param arg pointer to the CAM ccb for this IO
1552  * @param seg DMA address/length pairs
1553  * @param nseg number of DMA address/length pairs
1554  * @param error any errors while mapping the IO
1555  */
1556 static void
1557 ocs_scsi_dmamap_load(void *arg, bus_dma_segment_t *seg, int nseg, int error)
1558 {
1559         ocs_dmamap_load_arg_t *sglarg = (ocs_dmamap_load_arg_t*) arg;
1560
1561         if (error) {
1562                 printf("%s: seg=%p nseg=%d error=%d\n",
1563                                 __func__, seg, nseg, error);
1564                 sglarg->rc = -1;
1565         } else {
1566                 uint32_t i = 0;
1567                 uint32_t c = 0;
1568
1569                 if ((sglarg->sgl_count + nseg) > sglarg->sgl_max) {
1570                         printf("%s: sgl_count=%d nseg=%d max=%d\n", __func__,
1571                                 sglarg->sgl_count, nseg, sglarg->sgl_max);
1572                         sglarg->rc = -2;
1573                         return;
1574                 }
1575
1576                 for (i = 0, c = sglarg->sgl_count; i < nseg; i++, c++) {
1577                         sglarg->sgl[c].addr = seg[i].ds_addr;
1578                         sglarg->sgl[c].len  = seg[i].ds_len;
1579                 }
1580
1581                 sglarg->sgl_count = c;
1582
1583                 sglarg->rc = 0;
1584         }
1585 }
1586
1587 /**
1588  * @brief Build a scatter-gather list from a CAM CCB
1589  *
1590  * @param ocs the driver instance's software context
1591  * @param ccb pointer to the CCB
1592  * @param io pointer to the previously allocated IO object
1593  * @param sgl pointer to SGL
1594  * @param sgl_max number of entries in sgl
1595  *
1596  * @return 0 on success, non-zero otherwise
1597  */
1598 static int32_t
1599 ocs_build_scsi_sgl(struct ocs_softc *ocs, union ccb *ccb, ocs_io_t *io,
1600                 ocs_scsi_sgl_t *sgl, uint32_t sgl_max)
1601 {
1602         ocs_dmamap_load_arg_t dmaarg;
1603         int32_t err = 0;
1604
1605         if (!ocs || !ccb || !io || !sgl) {
1606                 printf("%s: bad param o=%p c=%p i=%p s=%p\n", __func__,
1607                                 ocs, ccb, io, sgl);
1608                 return -1;
1609         }
1610
1611         io->tgt_io.flags &= ~OCS_CAM_IO_F_DMAPPED;
1612
1613         dmaarg.sgl = sgl;
1614         dmaarg.sgl_count = 0;
1615         dmaarg.sgl_max = sgl_max;
1616         dmaarg.rc = 0;
1617
1618         err = bus_dmamap_load_ccb(ocs->buf_dmat, io->tgt_io.dmap, ccb,
1619                         ocs_scsi_dmamap_load, &dmaarg, 0);
1620
1621         if (err || dmaarg.rc) {
1622                 device_printf(
1623                         ocs->dev, "%s: bus_dmamap_load_ccb error (%d %d)\n",
1624                                 __func__, err, dmaarg.rc);
1625                 return -1;
1626         }
1627
1628         io->tgt_io.flags |= OCS_CAM_IO_F_DMAPPED;
1629         return dmaarg.sgl_count;
1630 }
1631
1632 /**
1633  * @ingroup cam_io
1634  * @brief Send a target IO
1635  *
1636  * @param ocs the driver instance's software context
1637  * @param ccb pointer to the CCB
1638  *
1639  * @return 0 on success, non-zero otherwise
1640  */
1641 static int32_t
1642 ocs_target_io(struct ocs_softc *ocs, union ccb *ccb)
1643 {
1644         struct ccb_scsiio *csio = &ccb->csio;
1645         ocs_io_t *io = NULL;
1646         uint32_t cam_dir = ccb->ccb_h.flags & CAM_DIR_MASK;
1647         bool sendstatus = ccb->ccb_h.flags & CAM_SEND_STATUS;
1648         uint32_t xferlen = csio->dxfer_len;
1649         int32_t rc = 0;
1650
1651         io = ocs_scsi_find_io(ocs, csio->tag_id);
1652         if (io == NULL) {
1653                 ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
1654                 panic("bad tag value");
1655                 return 1;
1656         }
1657
1658         /* Received an ABORT TASK for this IO */
1659         if (io->tgt_io.flags & OCS_CAM_IO_F_ABORT_RECV) {
1660                 /*device_printf(ocs->dev,
1661                         "%s: XPT_CONT_TARGET_IO state=%d tag=%#x xid=%#x flags=%#x\n",
1662                         __func__, io->tgt_io.state, io->tag, io->init_task_tag,
1663                         io->tgt_io.flags);*/
1664                 io->tgt_io.flags |= OCS_CAM_IO_F_ABORT_CAM;
1665
1666                 if (ccb->ccb_h.flags & CAM_SEND_STATUS) {
1667                         ocs_set_ccb_status(ccb, CAM_REQ_CMP);
1668                         ocs_target_io_free(io);
1669                         return 1;
1670                 } 
1671
1672                 ocs_set_ccb_status(ccb, CAM_REQ_ABORTED);
1673
1674                 return 1;
1675         }
1676
1677         io->tgt_io.app = ccb;
1678
1679         ocs_set_ccb_status(ccb, CAM_REQ_INPROG);
1680         ccb->ccb_h.status |= CAM_SIM_QUEUED;
1681
1682         csio->ccb_h.ccb_ocs_ptr = ocs;
1683         csio->ccb_h.ccb_io_ptr  = io;
1684
1685         if ((sendstatus && (xferlen == 0))) {
1686                 ocs_scsi_cmd_resp_t     resp = { 0 };
1687
1688                 ocs_assert(ccb->ccb_h.flags & CAM_SEND_STATUS, -1);
1689
1690                 io->tgt_io.state = OCS_CAM_IO_RESP;
1691
1692                 resp.scsi_status = csio->scsi_status;
1693
1694                 if (ccb->ccb_h.flags & CAM_SEND_SENSE) {
1695                         resp.sense_data = (uint8_t *)&csio->sense_data;
1696                         resp.sense_data_length = csio->sense_len;
1697                 }
1698
1699                 resp.residual = io->exp_xfer_len - io->transferred;
1700                 rc = ocs_scsi_send_resp(io, 0, &resp, ocs_scsi_target_io_cb, ccb);
1701
1702         } else if (xferlen != 0) {
1703                 ocs_scsi_sgl_t sgl[OCS_FC_MAX_SGL];
1704                 int32_t sgl_count = 0;
1705
1706                 io->tgt_io.state = OCS_CAM_IO_DATA;
1707                 
1708                 if (sendstatus)
1709                         io->tgt_io.sendresp = 1;
1710
1711                 sgl_count = ocs_build_scsi_sgl(ocs, ccb, io, sgl, ARRAY_SIZE(sgl));
1712                 if (sgl_count > 0) {
1713                         if (cam_dir == CAM_DIR_IN) {
1714                                 rc = ocs_scsi_send_rd_data(io, 0, NULL, sgl,
1715                                                 sgl_count, csio->dxfer_len,
1716                                                 ocs_scsi_target_io_cb, ccb);
1717                         } else if (cam_dir == CAM_DIR_OUT) {
1718                                 rc = ocs_scsi_recv_wr_data(io, 0, NULL, sgl,
1719                                                 sgl_count, csio->dxfer_len,
1720                                                 ocs_scsi_target_io_cb, ccb);
1721                         } else {
1722                                 device_printf(ocs->dev, "%s:"
1723                                                 " unknown CAM direction %#x\n",
1724                                                 __func__, cam_dir);
1725                                 ocs_set_ccb_status(ccb, CAM_REQ_INVALID);
1726                                 rc = 1;
1727                         }
1728                 } else {
1729                         device_printf(ocs->dev, "%s: building SGL failed\n",
1730                                                 __func__);
1731                         ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
1732                         rc = 1;
1733                 }
1734         } else {
1735                 device_printf(ocs->dev, "%s: Wrong value xfer and sendstatus"
1736                                         " are 0 \n", __func__);
1737                 ocs_set_ccb_status(ccb, CAM_REQ_INVALID);
1738                 rc = 1;
1739         }
1740
1741         if (rc) {
1742                 ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
1743                 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1744                 io->tgt_io.state = OCS_CAM_IO_DATA_DONE;
1745                 device_printf(ocs->dev, "%s: CTIO state=%d tag=%#x\n",
1746                                 __func__, io->tgt_io.state, io->tag);
1747         if ((sendstatus && (xferlen == 0))) {
1748                         ocs_target_io_free(io);
1749                 }
1750         }
1751
1752         return rc;
1753 }
1754
1755 static int32_t
1756 ocs_target_tmf_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status, uint32_t flags,
1757                 void *arg)
1758 {
1759
1760         /*device_printf(io->ocs->dev, "%s: tag=%x io=%p s=%#x\n",
1761                          __func__, io->tag, io, scsi_status);*/
1762         ocs_scsi_io_complete(io);
1763
1764         return 0;
1765 }
1766
1767 /**
1768  * @ingroup cam_io
1769  * @brief Send an initiator IO
1770  *
1771  * @param ocs the driver instance's software context
1772  * @param ccb pointer to the CCB
1773  *
1774  * @return 0 on success, non-zero otherwise
1775  */
1776 static int32_t
1777 ocs_initiator_io(struct ocs_softc *ocs, union ccb *ccb)
1778 {
1779         int32_t rc;
1780         struct ccb_scsiio *csio = &ccb->csio;
1781         struct ccb_hdr *ccb_h = &csio->ccb_h;
1782         ocs_node_t *node = NULL;
1783         ocs_io_t *io = NULL;
1784         ocs_scsi_sgl_t sgl[OCS_FC_MAX_SGL];
1785         int32_t sgl_count;
1786         ocs_fcport      *fcp;
1787
1788         fcp = FCPORT(ocs, cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path)));
1789
1790         if (fcp->tgt[ccb_h->target_id].state == OCS_TGT_STATE_LOST) {
1791                 device_printf(ocs->dev, "%s: device LOST %d\n", __func__,
1792                                                         ccb_h->target_id);
1793                 return CAM_REQUEUE_REQ;
1794         }
1795
1796         if (fcp->tgt[ccb_h->target_id].state == OCS_TGT_STATE_NONE) {
1797                 device_printf(ocs->dev, "%s: device not ready %d\n", __func__,
1798                                                         ccb_h->target_id);
1799                 return CAM_SEL_TIMEOUT;
1800         }
1801
1802         node = ocs_node_get_instance(ocs, fcp->tgt[ccb_h->target_id].node_id);
1803         if (node == NULL) {
1804                 device_printf(ocs->dev, "%s: no device %d\n", __func__,
1805                                                         ccb_h->target_id);
1806                 return CAM_SEL_TIMEOUT;
1807         }
1808
1809         if (!node->targ) {
1810                 device_printf(ocs->dev, "%s: not target device %d\n", __func__,
1811                                                         ccb_h->target_id);
1812                 return CAM_SEL_TIMEOUT;
1813         }
1814
1815         io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_ORIGINATOR);
1816         if (io == NULL) {
1817                 device_printf(ocs->dev, "%s: unable to alloc IO\n", __func__);
1818                 return -1;
1819         }
1820
1821         /* eventhough this is INI, use target structure as ocs_build_scsi_sgl
1822          * only references the tgt_io part of an ocs_io_t */
1823         io->tgt_io.app = ccb;
1824
1825         csio->ccb_h.ccb_ocs_ptr = ocs;
1826         csio->ccb_h.ccb_io_ptr  = io;
1827
1828         sgl_count = ocs_build_scsi_sgl(ocs, ccb, io, sgl, ARRAY_SIZE(sgl));
1829         if (sgl_count < 0) {
1830                 ocs_scsi_io_free(io);
1831                 device_printf(ocs->dev, "%s: building SGL failed\n", __func__);
1832                 return -1;
1833         }
1834
1835         if (ccb->ccb_h.timeout == CAM_TIME_INFINITY) {
1836                 io->timeout = 0;
1837         } else if (ccb->ccb_h.timeout == CAM_TIME_DEFAULT) {
1838                 io->timeout = OCS_CAM_IO_TIMEOUT;
1839         } else {
1840                 io->timeout = ccb->ccb_h.timeout;
1841         }
1842
1843         switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
1844         case CAM_DIR_NONE:
1845                 rc = ocs_scsi_send_nodata_io(node, io, ccb_h->target_lun,
1846                                 ccb->ccb_h.flags & CAM_CDB_POINTER ? 
1847                                 csio->cdb_io.cdb_ptr: csio->cdb_io.cdb_bytes,
1848                                 csio->cdb_len,
1849                                 ocs_scsi_initiator_io_cb, ccb);
1850                 break;
1851         case CAM_DIR_IN:
1852                 rc = ocs_scsi_send_rd_io(node, io, ccb_h->target_lun,
1853                                 ccb->ccb_h.flags & CAM_CDB_POINTER ? 
1854                                 csio->cdb_io.cdb_ptr: csio->cdb_io.cdb_bytes,
1855                                 csio->cdb_len,
1856                                 NULL,
1857                                 sgl, sgl_count, csio->dxfer_len,
1858                                 ocs_scsi_initiator_io_cb, ccb);
1859                 break;
1860         case CAM_DIR_OUT:
1861                 rc = ocs_scsi_send_wr_io(node, io, ccb_h->target_lun,
1862                                 ccb->ccb_h.flags & CAM_CDB_POINTER ? 
1863                                 csio->cdb_io.cdb_ptr: csio->cdb_io.cdb_bytes,
1864                                 csio->cdb_len,
1865                                 NULL,
1866                                 sgl, sgl_count, csio->dxfer_len,
1867                                 ocs_scsi_initiator_io_cb, ccb);
1868                 break;
1869         default:
1870                 panic("%s invalid data direction %08x\n", __func__, 
1871                                                         ccb->ccb_h.flags);
1872                 break;
1873         }
1874
1875         return rc;
1876 }
1877
1878 static uint32_t
1879 ocs_fcp_change_role(struct ocs_softc *ocs, ocs_fcport *fcp, uint32_t new_role)
1880 {
1881
1882         uint32_t rc = 0, was = 0, i = 0;
1883         ocs_vport_spec_t *vport = fcp->vport;
1884
1885         for (was = 0, i = 0; i < (ocs->num_vports + 1); i++) {
1886                 if (FCPORT(ocs, i)->role != KNOB_ROLE_NONE)
1887                 was++;
1888         }
1889
1890         // Physical port        
1891         if ((was == 0) || (vport == NULL)) { 
1892                 fcp->role = new_role;
1893                 if (vport == NULL) {
1894                         ocs->enable_ini = (new_role & KNOB_ROLE_INITIATOR)? 1:0;
1895                         ocs->enable_tgt = (new_role & KNOB_ROLE_TARGET)? 1:0;
1896                 } else {
1897                         vport->enable_ini = (new_role & KNOB_ROLE_INITIATOR)? 1:0;
1898                         vport->enable_tgt = (new_role & KNOB_ROLE_TARGET)? 1:0;
1899                 }
1900
1901                 rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE);
1902                 if (rc) {
1903                         ocs_log_debug(ocs, "port offline failed : %d\n", rc);
1904                 }
1905
1906                 rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE);
1907                 if (rc) {
1908                         ocs_log_debug(ocs, "port online failed : %d\n", rc);
1909                 }
1910                 
1911                 return 0;
1912         }
1913
1914         if ((fcp->role != KNOB_ROLE_NONE)){
1915                 fcp->role = new_role;
1916                 vport->enable_ini = (new_role & KNOB_ROLE_INITIATOR)? 1:0;
1917                 vport->enable_tgt = (new_role & KNOB_ROLE_TARGET)? 1:0;
1918                 /* New Sport will be created in sport deleted cb */
1919                 return ocs_sport_vport_del(ocs, ocs->domain, vport->wwpn, vport->wwnn);
1920         }
1921
1922         fcp->role = new_role;
1923
1924         vport->enable_ini = (new_role & KNOB_ROLE_INITIATOR)? 1:0;
1925         vport->enable_tgt = (new_role & KNOB_ROLE_TARGET)? 1:0;
1926
1927         if (fcp->role != KNOB_ROLE_NONE) {
1928                 return ocs_sport_vport_alloc(ocs->domain, vport);
1929         }
1930
1931         return (0);
1932 }
1933
1934 /**
1935  * @ingroup cam_api
1936  * @brief Process CAM actions
1937  *
1938  * The driver supplies this routine to the CAM during intialization and
1939  * is the main entry point for processing CAM Control Blocks (CCB)
1940  *
1941  * @param sim pointer to the SCSI Interface Module
1942  * @param ccb CAM control block
1943  *
1944  * @todo
1945  *  - populate path inquiry data via info retrieved from SLI port
1946  */
1947 static void
1948 ocs_action(struct cam_sim *sim, union ccb *ccb)
1949 {
1950         struct ocs_softc *ocs = (struct ocs_softc *)cam_sim_softc(sim);
1951         struct ccb_hdr  *ccb_h = &ccb->ccb_h;
1952
1953         int32_t rc, bus;
1954         bus = cam_sim_bus(sim);
1955
1956         switch (ccb_h->func_code) {
1957         case XPT_SCSI_IO:
1958
1959                 if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
1960                         if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) {
1961                                 ccb->ccb_h.status = CAM_REQ_INVALID;
1962                                 xpt_done(ccb);
1963                                 break;
1964                         }
1965                 }
1966
1967                 rc = ocs_initiator_io(ocs, ccb);
1968                 if (0 == rc) {
1969                         ocs_set_ccb_status(ccb, CAM_REQ_INPROG | CAM_SIM_QUEUED);
1970                         break;
1971                 } else {
1972                         if (rc == CAM_REQUEUE_REQ) {
1973                                 cam_freeze_devq(ccb->ccb_h.path);
1974                                 cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 100, 0);
1975                                 ccb->ccb_h.status = CAM_REQUEUE_REQ;
1976                                 xpt_done(ccb);
1977                                 break;
1978                         }
1979
1980                         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1981                         if (rc > 0) {
1982                                 ocs_set_ccb_status(ccb, rc);
1983                         } else {
1984                                 ocs_set_ccb_status(ccb, CAM_SEL_TIMEOUT);
1985                         }
1986                 }
1987                 xpt_done(ccb);
1988                 break;
1989         case XPT_PATH_INQ:
1990         {
1991                 struct ccb_pathinq *cpi = &ccb->cpi;
1992                 struct ccb_pathinq_settings_fc *fc = &cpi->xport_specific.fc;
1993                 ocs_fcport *fcp = FCPORT(ocs, bus);
1994
1995                 uint64_t wwn = 0;
1996                 ocs_xport_stats_t value;
1997
1998                 cpi->version_num = 1;
1999
2000                 cpi->protocol = PROTO_SCSI;
2001                 cpi->protocol_version = SCSI_REV_SPC;
2002
2003                 if (ocs->ocs_xport == OCS_XPORT_FC) {
2004                         cpi->transport = XPORT_FC;
2005                 } else {
2006                         cpi->transport = XPORT_UNKNOWN;
2007                 }
2008
2009                 cpi->transport_version = 0;
2010
2011                 /* Set the transport parameters of the SIM */
2012                 ocs_xport_status(ocs->xport, OCS_XPORT_LINK_SPEED, &value);
2013                 fc->bitrate = value.value * 1000;       /* speed in Mbps */
2014
2015                 wwn = *((uint64_t *)ocs_scsi_get_property_ptr(ocs, OCS_SCSI_WWPN));
2016                 fc->wwpn = be64toh(wwn);
2017
2018                 wwn = *((uint64_t *)ocs_scsi_get_property_ptr(ocs, OCS_SCSI_WWNN));
2019                 fc->wwnn = be64toh(wwn);
2020
2021                 fc->port = fcp->fc_id;
2022
2023                 if (ocs->config_tgt) {
2024                         cpi->target_sprt =
2025                                 PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO;
2026                 }
2027
2028                 cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED;
2029                 cpi->hba_misc |= PIM_EXTLUNS | PIM_NOSCAN;
2030
2031                 cpi->hba_inquiry = PI_TAG_ABLE; 
2032                 cpi->max_target = OCS_MAX_TARGETS;
2033                 cpi->initiator_id = ocs->max_remote_nodes + 1;
2034
2035                 if (!ocs->enable_ini) {
2036                         cpi->hba_misc |= PIM_NOINITIATOR;
2037                 }
2038
2039                 cpi->max_lun = OCS_MAX_LUN;
2040                 cpi->bus_id = cam_sim_bus(sim);
2041
2042                 /* Need to supply a base transfer speed prior to linking up
2043                  * Worst case, this would be FC 1Gbps */
2044                 cpi->base_transfer_speed = 1 * 1000 * 1000;
2045
2046                 /* Calculate the max IO supported
2047                  * Worst case would be an OS page per SGL entry */
2048                 cpi->maxio = PAGE_SIZE * 
2049                         (ocs_scsi_get_property(ocs, OCS_SCSI_MAX_SGL) - 1);
2050
2051                 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
2052                 strncpy(cpi->hba_vid, "Emulex", HBA_IDLEN);
2053                 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
2054                 cpi->unit_number = cam_sim_unit(sim);
2055
2056                 cpi->ccb_h.status = CAM_REQ_CMP;
2057                 xpt_done(ccb);
2058                 break;
2059         }
2060         case XPT_GET_TRAN_SETTINGS:
2061         {
2062                 struct ccb_trans_settings *cts = &ccb->cts;
2063                 struct ccb_trans_settings_scsi *scsi = &cts->proto_specific.scsi;
2064                 struct ccb_trans_settings_fc *fc = &cts->xport_specific.fc;
2065                 ocs_xport_stats_t value;
2066                 ocs_fcport *fcp = FCPORT(ocs, bus);
2067                 ocs_fc_target_t *tgt = NULL;
2068
2069                 if (ocs->ocs_xport != OCS_XPORT_FC) {
2070                         ocs_set_ccb_status(ccb, CAM_REQ_INVALID);
2071                         xpt_done(ccb);
2072                         break;
2073                 }
2074
2075                 if (cts->ccb_h.target_id > OCS_MAX_TARGETS) {
2076                         ocs_set_ccb_status(ccb, CAM_DEV_NOT_THERE);
2077                         xpt_done(ccb);
2078                         break;
2079                 }
2080
2081                 tgt = &fcp->tgt[cts->ccb_h.target_id];
2082                 if (tgt->state == OCS_TGT_STATE_NONE) { 
2083                         ocs_set_ccb_status(ccb, CAM_DEV_NOT_THERE);
2084                         xpt_done(ccb);
2085                         break;
2086                 }
2087
2088                 cts->protocol = PROTO_SCSI;
2089                 cts->protocol_version = SCSI_REV_SPC2;
2090                 cts->transport = XPORT_FC;
2091                 cts->transport_version = 2;
2092
2093                 scsi->valid = CTS_SCSI_VALID_TQ;
2094                 scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
2095
2096                 /* speed in Mbps */
2097                 ocs_xport_status(ocs->xport, OCS_XPORT_LINK_SPEED, &value);
2098                 fc->bitrate = value.value * 100;
2099
2100                 fc->wwpn = tgt->wwpn;
2101
2102                 fc->wwnn = tgt->wwnn;
2103
2104                 fc->port = tgt->port_id;
2105
2106                 fc->valid = CTS_FC_VALID_SPEED |
2107                         CTS_FC_VALID_WWPN |
2108                         CTS_FC_VALID_WWNN |
2109                         CTS_FC_VALID_PORT;
2110
2111                 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2112                 xpt_done(ccb);
2113                 break;
2114         }
2115         case XPT_SET_TRAN_SETTINGS:
2116                 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2117                 xpt_done(ccb);
2118                 break;
2119
2120         case XPT_CALC_GEOMETRY:
2121                 cam_calc_geometry(&ccb->ccg, TRUE);
2122                 xpt_done(ccb);
2123                 break;
2124
2125         case XPT_GET_SIM_KNOB:
2126         {
2127                 struct ccb_sim_knob *knob = &ccb->knob;
2128                 uint64_t wwn = 0;
2129                 ocs_fcport *fcp = FCPORT(ocs, bus);
2130
2131                 if (ocs->ocs_xport != OCS_XPORT_FC) {
2132                         ocs_set_ccb_status(ccb, CAM_REQ_INVALID);
2133                         xpt_done(ccb);
2134                         break;
2135                 }
2136                 
2137                 if (bus == 0) {
2138                         wwn = *((uint64_t *)ocs_scsi_get_property_ptr(ocs,
2139                                                 OCS_SCSI_WWNN));
2140                         knob->xport_specific.fc.wwnn = be64toh(wwn);
2141
2142                         wwn = *((uint64_t *)ocs_scsi_get_property_ptr(ocs,
2143                                                 OCS_SCSI_WWPN));
2144                         knob->xport_specific.fc.wwpn = be64toh(wwn);
2145                 } else {
2146                         knob->xport_specific.fc.wwnn = fcp->vport->wwnn;
2147                         knob->xport_specific.fc.wwpn = fcp->vport->wwpn;
2148                 }
2149
2150                 knob->xport_specific.fc.role = fcp->role;
2151                 knob->xport_specific.fc.valid = KNOB_VALID_ADDRESS |
2152                                                 KNOB_VALID_ROLE;
2153
2154                 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2155                 xpt_done(ccb);
2156                 break;
2157         }
2158         case XPT_SET_SIM_KNOB:
2159         {
2160                 struct ccb_sim_knob *knob = &ccb->knob;
2161                 bool role_changed = FALSE;
2162                 ocs_fcport *fcp = FCPORT(ocs, bus);
2163
2164                 if (ocs->ocs_xport != OCS_XPORT_FC) {
2165                         ocs_set_ccb_status(ccb, CAM_REQ_INVALID);
2166                         xpt_done(ccb);
2167                         break;
2168                 }
2169                         
2170                 if (knob->xport_specific.fc.valid & KNOB_VALID_ADDRESS) {
2171                         device_printf(ocs->dev, 
2172                                 "%s: XPT_SET_SIM_KNOB wwnn=%llx wwpn=%llx\n",
2173                                         __func__,
2174                                         (unsigned long long)knob->xport_specific.fc.wwnn,
2175                                         (unsigned long long)knob->xport_specific.fc.wwpn);
2176                 }
2177
2178                 if (knob->xport_specific.fc.valid & KNOB_VALID_ROLE) {
2179                         switch (knob->xport_specific.fc.role) {
2180                         case KNOB_ROLE_NONE:
2181                                 if (fcp->role != KNOB_ROLE_NONE) {
2182                                         role_changed = TRUE;
2183                                 }
2184                                 break;
2185                         case KNOB_ROLE_TARGET:
2186                                 if (fcp->role != KNOB_ROLE_TARGET) {
2187                                         role_changed = TRUE;
2188                                 }
2189                                 break;
2190                         case KNOB_ROLE_INITIATOR:
2191                                 if (fcp->role != KNOB_ROLE_INITIATOR) {
2192                                         role_changed = TRUE;
2193                                 }
2194                                 break;
2195                         case KNOB_ROLE_BOTH:
2196                                 if (fcp->role != KNOB_ROLE_BOTH) {
2197                                         role_changed = TRUE;
2198                                 }
2199                                 break;
2200                         default:
2201                                 device_printf(ocs->dev,
2202                                         "%s: XPT_SET_SIM_KNOB unsupported role: %d\n",
2203                                         __func__, knob->xport_specific.fc.role);
2204                         }
2205
2206                         if (role_changed) {
2207                                 device_printf(ocs->dev,
2208                                                 "BUS:%d XPT_SET_SIM_KNOB old_role: %d new_role: %d\n",
2209                                                 bus, fcp->role, knob->xport_specific.fc.role);
2210
2211                                 ocs_fcp_change_role(ocs, fcp, knob->xport_specific.fc.role);
2212                         }
2213                 }
2214
2215                 
2216
2217                 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2218                 xpt_done(ccb);
2219                 break;
2220         }
2221         case XPT_ABORT:
2222         {
2223                 union ccb *accb = ccb->cab.abort_ccb;
2224
2225                 switch (accb->ccb_h.func_code) {
2226                 case XPT_ACCEPT_TARGET_IO:
2227                         ocs_abort_atio(ocs, ccb);
2228                         break;
2229                 case XPT_IMMEDIATE_NOTIFY:
2230                         ocs_abort_inot(ocs, ccb);
2231                         break;
2232                 case XPT_SCSI_IO:
2233                         rc = ocs_abort_initiator_io(ocs, accb);
2234                         if (rc) {
2235                                 ccb->ccb_h.status = CAM_UA_ABORT;
2236                         } else {
2237                                 ccb->ccb_h.status = CAM_REQ_CMP;
2238                         }
2239
2240                         break;
2241                 default:
2242                         printf("abort of unknown func %#x\n",
2243                                         accb->ccb_h.func_code);
2244                         ccb->ccb_h.status = CAM_REQ_INVALID;
2245                         break;
2246                 }
2247                 break;
2248         }
2249         case XPT_RESET_BUS:
2250                 if (ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE) == 0) {
2251                         rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE);
2252                         if (rc) {
2253                                 ocs_log_debug(ocs, "Failed to bring port online"
2254                                                                 " : %d\n", rc);
2255                         }
2256                         ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2257                 } else {
2258                         ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
2259                 }
2260                 xpt_done(ccb);
2261                 break;
2262         case XPT_RESET_DEV:
2263         {
2264                 ocs_node_t      *node = NULL;
2265                 ocs_io_t        *io = NULL;
2266                 int32_t         rc = 0;
2267                 ocs_fcport *fcp = FCPORT(ocs, bus);
2268
2269                 node = ocs_node_get_instance(ocs, fcp->tgt[ccb_h->target_id].node_id);
2270                 if (node == NULL) {
2271                         device_printf(ocs->dev, "%s: no device %d\n",
2272                                                 __func__, ccb_h->target_id);
2273                         ocs_set_ccb_status(ccb, CAM_DEV_NOT_THERE);
2274                         xpt_done(ccb);
2275                         break;
2276                 }
2277
2278                 io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_ORIGINATOR);
2279                 if (io == NULL) {
2280                         device_printf(ocs->dev, "%s: unable to alloc IO\n",
2281                                                                  __func__);
2282                         ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
2283                         xpt_done(ccb);
2284                         break;
2285                 }
2286
2287                 rc = ocs_scsi_send_tmf(node, io, NULL, ccb_h->target_lun,
2288                                 OCS_SCSI_TMF_LOGICAL_UNIT_RESET,
2289                                 NULL, 0, 0,     /* sgl, sgl_count, length */
2290                                 ocs_initiator_tmf_cb, NULL/*arg*/);
2291
2292                 if (rc) {
2293                         ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
2294                 } else {
2295                         ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2296                 }
2297                 
2298                 if (node->fcp2device) {
2299                         ocs_reset_crn(node, ccb_h->target_lun);
2300                 }
2301
2302                 xpt_done(ccb);
2303                 break;
2304         }
2305         case XPT_EN_LUN:        /* target support */
2306         {
2307                 ocs_tgt_resource_t *trsrc = NULL;
2308                 uint32_t        status = 0;
2309                 ocs_fcport *fcp = FCPORT(ocs, bus);
2310
2311                 device_printf(ocs->dev, "XPT_EN_LUN %sable %d:%d\n",
2312                                 ccb->cel.enable ? "en" : "dis",
2313                                 ccb->ccb_h.target_id,
2314                                 (unsigned int)ccb->ccb_h.target_lun);
2315
2316                 trsrc = ocs_tgt_resource_get(fcp, &ccb->ccb_h, &status);
2317                 if (trsrc) {
2318                         trsrc->enabled = ccb->cel.enable;
2319
2320                         /* Abort all ATIO/INOT on LUN disable */
2321                         if (trsrc->enabled == FALSE) {
2322                                 ocs_tgt_resource_abort(ocs, trsrc);
2323                         } else {
2324                                 STAILQ_INIT(&trsrc->atio);
2325                                 STAILQ_INIT(&trsrc->inot);
2326                         }
2327                         status = CAM_REQ_CMP;
2328                 }
2329
2330                 ocs_set_ccb_status(ccb, status);
2331                 xpt_done(ccb);
2332                 break;
2333         }
2334         /*
2335          * The flow of target IOs in CAM is:
2336          *  - CAM supplies a number of CCBs to the driver used for received
2337          *    commands.
2338          *  - when the driver receives a command, it copies the relevant
2339          *    information to the CCB and returns it to the CAM using xpt_done()
2340          *  - after the target server processes the request, it creates
2341          *    a new CCB containing information on how to continue the IO and 
2342          *    passes that to the driver
2343          *  - the driver processes the "continue IO" (a.k.a CTIO) CCB
2344          *  - once the IO completes, the driver returns the CTIO to the CAM 
2345          *    using xpt_done()
2346          */
2347         case XPT_ACCEPT_TARGET_IO:      /* used to inform upper layer of 
2348                                                 received CDB (a.k.a. ATIO) */
2349         case XPT_IMMEDIATE_NOTIFY:      /* used to inform upper layer of other
2350                                                          event (a.k.a. INOT) */
2351         {
2352                 ocs_tgt_resource_t *trsrc = NULL;
2353                 uint32_t        status = 0;
2354                 ocs_fcport *fcp = FCPORT(ocs, bus);
2355
2356                 /*printf("XPT_%s %p\n", ccb_h->func_code == XPT_ACCEPT_TARGET_IO ?
2357                                 "ACCEPT_TARGET_IO" : "IMMEDIATE_NOTIFY", ccb);*/
2358                 trsrc = ocs_tgt_resource_get(fcp, &ccb->ccb_h, &status);
2359                 if (trsrc == NULL) {
2360                         ocs_set_ccb_status(ccb, CAM_DEV_NOT_THERE);
2361                         xpt_done(ccb);
2362                         break;
2363                 }
2364
2365                 if (XPT_ACCEPT_TARGET_IO == ccb->ccb_h.func_code) {
2366                         struct ccb_accept_tio *atio = NULL;
2367
2368                         atio = (struct ccb_accept_tio *)ccb;
2369                         atio->init_id = 0x0badbeef;
2370                         atio->tag_id  = 0xdeadc0de;
2371
2372                         STAILQ_INSERT_TAIL(&trsrc->atio, &ccb->ccb_h, 
2373                                         sim_links.stqe);
2374                 } else {
2375                         STAILQ_INSERT_TAIL(&trsrc->inot, &ccb->ccb_h, 
2376                                         sim_links.stqe);
2377                 }
2378                 ccb->ccb_h.ccb_io_ptr  = NULL;
2379                 ccb->ccb_h.ccb_ocs_ptr = ocs;
2380                 ocs_set_ccb_status(ccb, CAM_REQ_INPROG);
2381                 /*
2382                  * These actions give resources to the target driver.
2383                  * If we didn't return here, this function would call
2384                  * xpt_done(), signaling to the upper layers that an
2385                  * IO or other event had arrived.
2386                  */
2387                 break;
2388         }
2389         case XPT_NOTIFY_ACKNOWLEDGE:
2390         {
2391                 ocs_io_t *io = NULL;
2392                 ocs_io_t *abortio = NULL;
2393
2394                 /* Get the IO reference for this tag */
2395                 io = ocs_scsi_find_io(ocs, ccb->cna2.tag_id);
2396                 if (io == NULL) {
2397                         device_printf(ocs->dev,
2398                                 "%s: XPT_NOTIFY_ACKNOWLEDGE no IO with tag %#x\n",
2399                                         __func__, ccb->cna2.tag_id);
2400                         ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
2401                         xpt_done(ccb);
2402                         break;
2403                 }
2404
2405                 abortio = io->tgt_io.app;
2406                 if (abortio) {
2407                         abortio->tgt_io.flags &= ~OCS_CAM_IO_F_ABORT_NOTIFY;
2408                         device_printf(ocs->dev,
2409                                 "%s: XPT_NOTIFY_ACK state=%d tag=%#x xid=%#x"
2410                                 " flags=%#x\n", __func__, abortio->tgt_io.state,
2411                                 abortio->tag, abortio->init_task_tag,
2412                                         abortio->tgt_io.flags);
2413                         /* TMF response was sent in abort callback */
2414                 } else {
2415                         ocs_scsi_send_tmf_resp(io, 
2416                                         OCS_SCSI_TMF_FUNCTION_COMPLETE,
2417                                         NULL, ocs_target_tmf_cb, NULL);
2418                 }
2419
2420                 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2421                 xpt_done(ccb);
2422                 break;
2423         }
2424         case XPT_CONT_TARGET_IO:        /* continue target IO, sending data/response (a.k.a. CTIO) */
2425                 if (ocs_target_io(ocs, ccb)) {
2426                         device_printf(ocs->dev, 
2427                                 "XPT_CONT_TARGET_IO failed flags=%x tag=%#x\n",
2428                                 ccb->ccb_h.flags, ccb->csio.tag_id);
2429                         xpt_done(ccb);
2430                 }
2431                 break;
2432         default:
2433                 device_printf(ocs->dev, "unhandled func_code = %#x\n",
2434                                 ccb_h->func_code);
2435                 ccb_h->status = CAM_REQ_INVALID;
2436                 xpt_done(ccb);
2437                 break;
2438         }
2439 }
2440
2441 /**
2442  * @ingroup cam_api
2443  * @brief Process events
2444  *
2445  * @param sim pointer to the SCSI Interface Module
2446  *
2447  */
2448 static void
2449 ocs_poll(struct cam_sim *sim)
2450 {
2451         printf("%s\n", __func__);
2452 }
2453
2454 static int32_t
2455 ocs_initiator_tmf_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status,
2456                 ocs_scsi_cmd_resp_t *rsp, uint32_t flags, void *arg)
2457 {
2458         int32_t rc = 0;
2459
2460         switch (scsi_status) {
2461         case OCS_SCSI_STATUS_GOOD:
2462         case OCS_SCSI_STATUS_NO_IO:
2463                 break;
2464         case OCS_SCSI_STATUS_CHECK_RESPONSE:
2465                 if (rsp->response_data_length == 0) {
2466                         ocs_log_test(io->ocs, "check response without data?!?\n");
2467                         rc = -1;
2468                         break;
2469                 }
2470
2471                 if (rsp->response_data[3] != 0) {
2472                         ocs_log_test(io->ocs, "TMF status %08x\n",
2473                                 be32toh(*((uint32_t *)rsp->response_data)));
2474                         rc = -1;
2475                         break;
2476                 }
2477                 break;
2478         default:
2479                 ocs_log_test(io->ocs, "status=%#x\n", scsi_status);
2480                 rc = -1;
2481         }
2482
2483         ocs_scsi_io_free(io);
2484
2485         return rc;
2486 }
2487
2488 /**
2489  * @brief lookup target resource structure
2490  *
2491  * Arbitrarily support
2492  *  - wildcard target ID + LU
2493  *  - 0 target ID + non-wildcard LU
2494  *
2495  * @param ocs the driver instance's software context
2496  * @param ccb_h pointer to the CCB header
2497  * @param status returned status value
2498  *
2499  * @return pointer to the target resource, NULL if none available (e.g. if LU
2500  *         is not enabled)
2501  */
2502 static ocs_tgt_resource_t *ocs_tgt_resource_get(ocs_fcport *fcp, 
2503                                 struct ccb_hdr *ccb_h, uint32_t *status)
2504 {
2505         target_id_t     tid = ccb_h->target_id;
2506         lun_id_t        lun = ccb_h->target_lun;
2507
2508         if (CAM_TARGET_WILDCARD == tid) {
2509                 if (CAM_LUN_WILDCARD != lun) {
2510                         *status = CAM_LUN_INVALID;
2511                         return NULL;
2512                 }
2513                 return &fcp->targ_rsrc_wildcard;
2514         } else {
2515                 if (lun < OCS_MAX_LUN) {
2516                         return &fcp->targ_rsrc[lun];
2517                 } else {
2518                         *status = CAM_LUN_INVALID;
2519                         return NULL;
2520                 }
2521         } 
2522
2523 }
2524
2525 static int32_t
2526 ocs_tgt_resource_abort(struct ocs_softc *ocs, ocs_tgt_resource_t *trsrc)
2527 {
2528         union ccb *ccb = NULL;
2529         uint32_t        count;
2530
2531         count = 0;
2532         do {
2533                 ccb = (union ccb *)STAILQ_FIRST(&trsrc->atio);
2534                 if (ccb) {
2535                         STAILQ_REMOVE_HEAD(&trsrc->atio, sim_links.stqe);
2536                         ccb->ccb_h.status = CAM_REQ_ABORTED;
2537                         xpt_done(ccb);
2538                         count++;
2539                 }
2540         } while (ccb);
2541
2542         count = 0;
2543         do {
2544                 ccb = (union ccb *)STAILQ_FIRST(&trsrc->inot);
2545                 if (ccb) {
2546                         STAILQ_REMOVE_HEAD(&trsrc->inot, sim_links.stqe);
2547                         ccb->ccb_h.status = CAM_REQ_ABORTED;
2548                         xpt_done(ccb);
2549                         count++;
2550                 }
2551         } while (ccb);
2552
2553         return 0;
2554 }
2555
2556 static void
2557 ocs_abort_atio(struct ocs_softc *ocs, union ccb *ccb)
2558 {
2559
2560         ocs_io_t        *aio = NULL;
2561         ocs_tgt_resource_t *trsrc = NULL;
2562         uint32_t        status = CAM_REQ_INVALID;
2563         struct ccb_hdr *cur = NULL;
2564         union ccb *accb = ccb->cab.abort_ccb;
2565
2566         int bus = cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path));
2567         ocs_fcport *fcp = FCPORT(ocs, bus); 
2568
2569         trsrc = ocs_tgt_resource_get(fcp, &accb->ccb_h, &status);
2570         if (trsrc != NULL) {
2571                 STAILQ_FOREACH(cur, &trsrc->atio, sim_links.stqe) {
2572                         if (cur != &accb->ccb_h) 
2573                                 continue;
2574
2575                         STAILQ_REMOVE(&trsrc->atio, cur, ccb_hdr,
2576                                                         sim_links.stqe);
2577                         accb->ccb_h.status = CAM_REQ_ABORTED;
2578                         xpt_done(accb);
2579                         ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2580                         return;
2581                 }
2582         }
2583
2584         /* if the ATIO has a valid IO pointer, CAM is telling
2585          * the driver that the ATIO (which represents the entire
2586          * exchange) has been aborted. */
2587
2588         aio = accb->ccb_h.ccb_io_ptr;
2589         if (aio == NULL) {
2590                 ccb->ccb_h.status = CAM_UA_ABORT;
2591                 return;
2592         }
2593
2594         device_printf(ocs->dev,
2595                         "%s: XPT_ABORT ATIO state=%d tag=%#x"
2596                         " xid=%#x flags=%#x\n", __func__, 
2597                         aio->tgt_io.state, aio->tag, 
2598                         aio->init_task_tag, aio->tgt_io.flags);
2599         /* Expectations are:
2600          *  - abort task was received
2601          *  - already aborted IO in the DEVICE
2602          *  - already received NOTIFY ACKNOWLEDGE */
2603
2604         if ((aio->tgt_io.flags & OCS_CAM_IO_F_ABORT_RECV) == 0) {
2605                 device_printf(ocs->dev, "%s: abort not received or io completed \n", __func__);
2606                 ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2607                 return;
2608         }
2609
2610         aio->tgt_io.flags |= OCS_CAM_IO_F_ABORT_CAM;
2611         ocs_target_io_free(aio);
2612         ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2613
2614         return;
2615 }
2616
2617 static void
2618 ocs_abort_inot(struct ocs_softc *ocs, union ccb *ccb)
2619 {
2620         ocs_tgt_resource_t *trsrc = NULL;
2621         uint32_t        status = CAM_REQ_INVALID;
2622         struct ccb_hdr *cur = NULL;
2623         union ccb *accb = ccb->cab.abort_ccb;
2624
2625         int bus = cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path));
2626         ocs_fcport *fcp = FCPORT(ocs, bus); 
2627
2628         trsrc = ocs_tgt_resource_get(fcp, &accb->ccb_h, &status);
2629         if (trsrc) {
2630                 STAILQ_FOREACH(cur, &trsrc->inot, sim_links.stqe) {
2631                         if (cur != &accb->ccb_h) 
2632                                 continue;
2633
2634                         STAILQ_REMOVE(&trsrc->inot, cur, ccb_hdr,
2635                                                         sim_links.stqe);
2636                         accb->ccb_h.status = CAM_REQ_ABORTED;
2637                         xpt_done(accb);
2638                         ocs_set_ccb_status(ccb, CAM_REQ_CMP);
2639                         return;
2640                 }
2641         }
2642
2643         ocs_set_ccb_status(ccb, CAM_UA_ABORT);
2644         return;
2645 }
2646
2647 static uint32_t
2648 ocs_abort_initiator_io(struct ocs_softc *ocs, union ccb *accb)
2649 {
2650
2651         ocs_node_t      *node = NULL;
2652         ocs_io_t        *io = NULL;
2653         int32_t         rc = 0;
2654         struct ccb_scsiio *csio = &accb->csio;
2655
2656         ocs_fcport *fcp = FCPORT(ocs, cam_sim_bus(xpt_path_sim((accb)->ccb_h.path)));
2657         node = ocs_node_get_instance(ocs, fcp->tgt[accb->ccb_h.target_id].node_id);
2658         if (node == NULL) {
2659                 device_printf(ocs->dev, "%s: no device %d\n", 
2660                                 __func__, accb->ccb_h.target_id);
2661                 ocs_set_ccb_status(accb, CAM_DEV_NOT_THERE);
2662                 xpt_done(accb);
2663                 return (-1);
2664         }
2665
2666         io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_ORIGINATOR);
2667         if (io == NULL) {
2668                 device_printf(ocs->dev,
2669                                 "%s: unable to alloc IO\n", __func__);
2670                 ocs_set_ccb_status(accb, CAM_REQ_CMP_ERR);
2671                 xpt_done(accb);
2672                 return (-1);
2673         }
2674
2675         rc = ocs_scsi_send_tmf(node, io, 
2676                         (ocs_io_t *)csio->ccb_h.ccb_io_ptr,
2677                         accb->ccb_h.target_lun,
2678                         OCS_SCSI_TMF_ABORT_TASK,
2679                         NULL, 0, 0,
2680                         ocs_initiator_tmf_cb, NULL/*arg*/);
2681
2682         return rc;
2683 }
2684
2685 void
2686 ocs_scsi_ini_ddump(ocs_textbuf_t *textbuf, ocs_scsi_ddump_type_e type, void *obj)
2687 {
2688         switch(type) {
2689         case OCS_SCSI_DDUMP_DEVICE: {
2690                 //ocs_t *ocs = obj;
2691                 break;
2692         }
2693         case OCS_SCSI_DDUMP_DOMAIN: {
2694                 //ocs_domain_t *domain = obj;
2695                 break;
2696         }
2697         case OCS_SCSI_DDUMP_SPORT: {
2698                 //ocs_sport_t *sport = obj;
2699                 break;
2700         }
2701         case OCS_SCSI_DDUMP_NODE: {
2702                 //ocs_node_t *node = obj;
2703                 break;
2704         }
2705         case OCS_SCSI_DDUMP_IO: {
2706                 //ocs_io_t *io = obj;
2707                 break;
2708         }
2709         default: {
2710                 break;
2711         }
2712         }
2713 }
2714
2715 void
2716 ocs_scsi_tgt_ddump(ocs_textbuf_t *textbuf, ocs_scsi_ddump_type_e type, void *obj)
2717 {
2718         switch(type) {
2719         case OCS_SCSI_DDUMP_DEVICE: {
2720                 //ocs_t *ocs = obj;
2721                 break;
2722         }
2723         case OCS_SCSI_DDUMP_DOMAIN: {
2724                 //ocs_domain_t *domain = obj;
2725                 break;
2726         }
2727         case OCS_SCSI_DDUMP_SPORT: {
2728                 //ocs_sport_t *sport = obj;
2729                 break;
2730         }
2731         case OCS_SCSI_DDUMP_NODE: {
2732                 //ocs_node_t *node = obj;
2733                 break;
2734         }
2735         case OCS_SCSI_DDUMP_IO: {
2736                 ocs_io_t *io = obj;
2737                 char *state_str = NULL;
2738
2739                 switch (io->tgt_io.state) {
2740                 case OCS_CAM_IO_FREE:
2741                         state_str = "FREE";
2742                         break;
2743                 case OCS_CAM_IO_COMMAND:
2744                         state_str = "COMMAND";
2745                         break;
2746                 case OCS_CAM_IO_DATA:
2747                         state_str = "DATA";
2748                         break;
2749                 case OCS_CAM_IO_DATA_DONE:
2750                         state_str = "DATA_DONE";
2751                         break;
2752                 case OCS_CAM_IO_RESP:
2753                         state_str = "RESP";
2754                         break;
2755                 default:
2756                         state_str = "xxx BAD xxx";
2757                 }
2758                 ocs_ddump_value(textbuf, "cam_st", "%s", state_str);
2759                 if (io->tgt_io.app) {
2760                         ocs_ddump_value(textbuf, "cam_flags", "%#x",
2761                                 ((union ccb *)(io->tgt_io.app))->ccb_h.flags);
2762                         ocs_ddump_value(textbuf, "cam_status", "%#x",
2763                                 ((union ccb *)(io->tgt_io.app))->ccb_h.status);
2764                 }
2765
2766                 break;
2767         }
2768         default: {
2769                 break;
2770         }
2771         }
2772 }
2773
2774 int32_t ocs_scsi_get_block_vaddr(ocs_io_t *io, uint64_t blocknumber,
2775                                 ocs_scsi_vaddr_len_t addrlen[],
2776                                 uint32_t max_addrlen, void **dif_vaddr)
2777 {
2778         return -1;
2779 }
2780
2781 uint32_t
2782 ocs_get_crn(ocs_node_t *node, uint8_t *crn, uint64_t lun)
2783 {
2784         uint32_t idx;
2785         struct ocs_lun_crn *lcrn = NULL;
2786         idx = lun % OCS_MAX_LUN;
2787
2788         lcrn = node->ini_node.lun_crn[idx];
2789
2790         if (lcrn == NULL) {
2791                 lcrn = ocs_malloc(node->ocs, sizeof(struct ocs_lun_crn),
2792                                         M_ZERO|M_NOWAIT);
2793                 if (lcrn == NULL) {
2794                         return (1);
2795                 }
2796                 
2797                 lcrn->lun = lun;
2798                 node->ini_node.lun_crn[idx] = lcrn;
2799         }
2800
2801         if (lcrn->lun != lun) {
2802                 return (1);
2803         }       
2804
2805         if (lcrn->crnseed == 0)
2806                 lcrn->crnseed = 1;
2807
2808         *crn = lcrn->crnseed++;
2809         return (0);
2810 }
2811
2812 void
2813 ocs_del_crn(ocs_node_t *node)
2814 {
2815         uint32_t i;
2816         struct ocs_lun_crn *lcrn = NULL;
2817
2818         for(i = 0; i < OCS_MAX_LUN; i++) {
2819                 lcrn = node->ini_node.lun_crn[i];
2820                 if (lcrn) {
2821                         ocs_free(node->ocs, lcrn, sizeof(*lcrn));
2822                 }
2823         }
2824
2825         return;
2826 }
2827
2828 void
2829 ocs_reset_crn(ocs_node_t *node, uint64_t lun)
2830 {
2831         uint32_t idx;
2832         struct ocs_lun_crn *lcrn = NULL;
2833         idx = lun % OCS_MAX_LUN;
2834
2835         lcrn = node->ini_node.lun_crn[idx];
2836         if (lcrn)
2837                 lcrn->crnseed = 0;
2838
2839         return;
2840 }