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