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